微调框不显示所选项目 [英] Spinner doesn't show the selected item

查看:62
本文介绍了微调框不显示所选项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在android中制作了一个简单的应用程序,该应用程序连接到服务器并获取帖子列表,然后我有一个 spinner ,其中包含了每个帖子的标题,您可以选择一个其中

Hi I have made a simple app in android that connects to a server and gets a list of posts, then I have a spinner that gets filled with the title of each post and you can select one of them.

一切正常,直到我必须选择帖子为止,我打开 spinner ,它显示了我选择的所有标题,但没有任何反应,该帖子未在 spinner 并且文本没有变化,我读了10篇关于Spinners的帖子,其中没有显示项目,但我无法使其工作,请帮助我,这是我的Java代码:

It all works until the point where I have to select a post, I open the spinner, it shows all the title I select one and nothing happens, the post is not selected in the spinner and the texts doesn't change, I read like 10 posts about spinners not showing the items but I couldn't make it work, please help me, this is my java code:

package com.example.lagarto.blog;

import android.graphics.Color;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import android.util.Log;
import android.widget.Spinner;

public class MainActivity extends AppCompatActivity {
    ArrayList<Post> archivo=new ArrayList<Post>();
    ArrayList<String> titulos=new ArrayList<String>();
    public ArrayAdapter<String> spinnerArrayAdapter;
    private static final String TAG= MainActivity.class.getSimpleName();
    private class GetDBConnection extends AsyncTask<Integer, Void, String>{
        @Override
        protected String doInBackground(Integer... params) {
            try{
                Connection conn= DBConnection.getInstance().getConnection();
                Statement st= conn.createStatement();
                String sql=("SELECT * FROM posts");
                ResultSet rs=st.executeQuery(sql);
                while(rs.next()) {
                    int id = rs.getInt("Id");
                    String title = rs.getString("Title");
                    String body = rs.getString("Body");
                    String date = rs.getString("Date");
                    Post post = new Post(id, title, body, date);
                    archivo.add(post);
                    System.out.println(archivo);
                }
                Log.d(TAG,"Terminado");
            }catch(SQLException e){
                e.printStackTrace();
            }
            return "Valido";
        }

        @Override
        protected void onPostExecute(String result) {
            Spinner spinner=(Spinner) findViewById(R.id.spinner);
            spinner.setVisibility(View.VISIBLE);
            for (Post i:archivo) {
                titulos.add(i.getTitle());
            }
            TextView title=(TextView) findViewById(R.id.title);
            TextView body=(TextView) findViewById(R.id.body);
            title.setVisibility(View.VISIBLE);
            body.setVisibility(View.VISIBLE);
            TextView connection=(TextView) findViewById(R.id.connection);
            connection.setVisibility(View.INVISIBLE);
            spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    spinnerArrayAdapter.notifyDataSetChanged();
                    Post resultado=archivo.get(position);
                    title.setText(resultado.getTitle());
                    body.setText(resultado.getBody());
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {
                    spinnerArrayAdapter.notifyDataSetChanged();
                    Post resultado=archivo.get(0);
                    title.setText(resultado.getTitle());
                    body.setText(resultado.getBody());
                }
            });

        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new GetDBConnection().execute(0);
        Spinner spinner=(Spinner) findViewById(R.id.spinner);
        spinnerArrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, titulos);
        spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(spinnerArrayAdapter);
        spinner.setSelection(1);
        System.out.println(archivo);



    }


}

这是我的xml代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.lagarto.blog.MainActivity">



    <TextView
        android:layout_width="400dp"
        android:layout_height="50dp"
        android:text="Hello World!"
        android:textSize="30dp"
        android:textAlignment="center"
        android:layout_alignParentEnd="true"
        android:id="@+id/title"
        android:layout_marginTop="40dp"
        android:visibility="invisible"
        />
    <TextView
        android:layout_width="400dp"
        android:layout_height="500dp"
        android:text="Hello World!"
        android:textSize="16dp"
        android:layout_marginTop="100dp"
        android:layout_alignParentEnd="true"
        android:id="@+id/body"
        android:visibility="invisible"
        />

    <Spinner
        android:layout_width="400dp"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/spinner"
        android:textSize="20dp"
        android:visibility="invisible"
        android:backgroundTint="@color/colorPrimaryDark"
        android:textAlignment="center"
        />

    <TextView
        android:text="Waiting for connection please wait"
        android:layout_width="400dp"
        android:layout_height="100dp"
        android:textSize="30dp"
        android:textAlignment="center"
        android:layout_marginTop="150dp"
        android:id="@+id/connection" />


</RelativeLayout>

推荐答案

好,这是我的评估:

TL; DR :

您尝试在后台线程上更新UI.

You tried to update the UI on a Background Thread.

说明:

这是您在 onCreate

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new GetDBConnection().execute(0);
    Spinner spinner=(Spinner) findViewById(R.id.spinner);
    spinnerArrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, titulos);
    spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(spinnerArrayAdapter);
    spinner.setSelection(1);
    System.out.println(archivo);
}

一些基于此的指针:

  • 在旋转器准备就绪之前,您调用了 GetDBConnection .您的 GetDBConnection 将在后台异步运行,因此,当您获取数据 并为微调器设置 onItemSelectedListener 时(我将在后面解释),则说明您在设置微调器时已创建了竞争条件.
  • 似乎您的微调器已装满,但这仍然不是一个好习惯.
  • 然后,使用 spinner.setSelection(1); 设置选择,确定异步调用是否已完成.我忘了这是否应该引发异常.
  • You called the GetDBConnection before your spinner is even ready. Your GetDBConnection will run Asynchronously in the background, so while you were fetching your data and setting onItemSelectedListener for your spinner (I'll explain later), you have created a race condition with you setting up your spinner.
  • It seems like your spinner is populated, but it was not a good practice nonetheless.
  • Then, you set the selection, whether the Asynchronous call has been completed or not using spinner.setSelection(1);. I forgot whether this should throw an exception or not.

现在转到您的 onPostExecute 代码段

@Override        
protected void onPostExecute(String result) {
    Spinner spinner=(Spinner) findViewById(R.id.spinner);
    spinner.setVisibility(View.VISIBLE);
    for (Post i:archivo) {
        titulos.add(i.getTitle());
    }
    TextView title=(TextView) findViewById(R.id.title);
    TextView body=(TextView) findViewById(R.id.body);
    title.setVisibility(View.VISIBLE);
    body.setVisibility(View.VISIBLE);
    TextView connection=(TextView) findViewById(R.id.connection);
    connection.setVisibility(View.INVISIBLE);
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            spinnerArrayAdapter.notifyDataSetChanged();
            Post resultado=archivo.get(position);
            title.setText(resultado.getTitle());
            body.setText(resultado.getBody());
        }
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            spinnerArrayAdapter.notifyDataSetChanged();
            Post resultado=archivo.get(0);
            title.setText(resultado.getTitle());
            body.setText(resultado.getBody());
        }
    });
}

  • 如果您想即时更新微调框的元素,还应该在Adapter中包含用于更新(添加,删除或更新)List元素的方法.
  • 就像我之前提到的,
  • 将侦听器置于 AsyncTask 中,虽然可能适用,但这不是一个好习惯.更不用说您也尝试更改UI(设置TextView值).这将产生错误,因为您的调用不在UI线程上.这就是为什么我说您应该将 AsyncTask 集中在仅
  • 上获取数据的原因

    • If you want to update your spinner's elements on the fly, you should also include methods to update (add, delete, or update) the List elements in your Adapter.
    • Like I mentioned earlier, putting a listener in an AsyncTask is, while perhaps applicable, not a good practice. Not to mention you try to change the UI, too (setting the TextView values). This will produce error because your call is not on the UI Thread. That's why I said you should focus the AsyncTask on fetching the data only
    • 假设您有自己的自定义适配器,这是我的自定义适配器,能够处理数据更新:

      Assuming you have your own Custom Adapter, here is my custom adapter that is capable to handle update of data:

      public abstract class CustomListAdapter<T> extends BaseAdapter {
          protected List<T> mData = new ArrayList<>();
          protected LayoutInflater mInflater;
          protected ViewHolder holder;
      
          /*truncated*/
      
          public void addItem(T item){
              mData.add(item);
              notifyDataSetChanged();
          }
      
          public void clear(){
              mData = new ArrayList<>();
              notifyDataSetChanged();
          }
      
          public void deleteItem(int position){
              mData.remove(position);
              notifyDataSetChanged();
          }
      
          public void fill(Collection<T> items){
              mData.addAll(items);
              notifyDataSetChanged();
          }
      }
      

      当然,这只是一个例子.

      Of course, this is just an example.

      摘要:

      尝试如下更新代码:

      //Declare your elements here first;
      
      TextView title;
      TextView body;
      TextView connection;
      Spinner spinner;
      
      private class GetDBConnection extends AsyncTask<Integer, Void, String>{
          @Override
          protected String doInBackground(Integer... params) {
              try{
                  Connection conn= DBConnection.getInstance().getConnection();
                  Statement st= conn.createStatement();
                  String sql=("SELECT * FROM posts");
                  ResultSet rs=st.executeQuery(sql);
                  while(rs.next()) {
                      int id = rs.getInt("Id");
                      String title = rs.getString("Title");
                      String body = rs.getString("Body");
                      String date = rs.getString("Date");
                      Post post = new Post(id, title, body, date);
                      archivo.add(post);
                      System.out.println(archivo);
                  }
                  Log.d(TAG,"Terminado");
              }catch(SQLException e){
                  e.printStackTrace();
              }
              return "Valido";
          }
      
          @Override
          protected void onPostExecute(String result) {
              /*
                  all code that changes your UI should resides in the UI Thread. This is still in Background Thread.
              */
              //Spinner spinner=(Spinner) findViewById(R.id.spinner); --> this is also unneccessary
              //spinner.setVisibility(View.VISIBLE);
      
              /*
                  something like this is possible as long as it doesn't change your UI.
              */
              for (Post i:archivo) {
                  titulos.add(i.getTitle());
                  /*
                  - update your Adapter List elements here.
                  */
              }
              // - also call your adapter notifyDataSetChanged here, if neccessary.
      
              //TextView title=(TextView) findViewById(R.id.title); --> unneccessary!
              //TextView body=(TextView) findViewById(R.id.body); --> unneccessary!
              //title.setVisibility(View.VISIBLE);
              //body.setVisibility(View.VISIBLE);
              //TextView connection=(TextView) findViewById(R.id.connection); --> unneccessary!
              //connection.setVisibility(View.INVISIBLE);
      
              /*
                  instead, you can call another method that resides in the UI Thread 
              */
              // updateUI();
              /*
                  or, execute them under runOnUIThread()
              */
              runOnUIThread(new Runnable(){
                  @Override
                  public void run(){
                      spinner.setVisibility(View.VISIBLE);
                      title.setVisibility(View.VISIBLE);
                      body.setVisibility(View.VISIBLE);
                      connection.setVisibility(View.INVISIBLE);
                  }
              });
          }
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              /*
                  you should initiate ALL your UI elements on the onCreate()
              */
              spinner=(Spinner) findViewById(R.id.spinner);
              title=(TextView) findViewById(R.id.title);
              body=(TextView) findViewById(R.id.body);
              connection=(TextView) findViewById(R.id.connection);
              spinnerArrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, titulos);
              spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
              /*
                  then, set your listeners
              */
              spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                  @Override
                  public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                      //spinnerArrayAdapter.notifyDataSetChanged(); --> this is unneccessary
                      Post resultado=archivo.get(position);
                      title.setText(resultado.getTitle());
                      body.setText(resultado.getBody());
                  }
                  @Override
                  public void onNothingSelected(AdapterView<?> parent) {
                      //spinnerArrayAdapter.notifyDataSetChanged(); --> this is unneccessary
                      Post resultado=archivo.get(0);
                      title.setText(resultado.getTitle());
                      body.setText(resultado.getBody());
                  }
              });
              spinner.setAdapter(spinnerArrayAdapter);
              System.out.println(archivo);
      
              new GetDBConnection().execute(0);   // --> After all has been set, then execute your AsyncTask.
          }
      
          private void updateUI(){
              spinner.setVisibility(View.VISIBLE);
              title.setVisibility(View.VISIBLE);
              body.setVisibility(View.VISIBLE);
              connection.setVisibility(View.INVISIBLE);
          }
      }
      

      希望这会有所帮助!

      这篇关于微调框不显示所选项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆