Spinner不显示所选项目

时间:2016-10-20 20:45:12

标签: java android xml android-layout spinner

您好我已经在Android中创建了一个简单的应用程序连接到服务器并获取帖子列表,然后我有一个GameViewController填充每个帖子的标题,您可以选择其中一个。

这一切都有效,直到我必须选择一个帖子,我打开spinner,它显示我选择的所有标题,没有任何反应,spinner中没有选择帖子并且文本没有变化,我读了10篇关于微调器没有显示项目的帖子,但是我无法使它工作,请帮帮我,这是我的java代码:

spinner

这是我的xml代码:

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);



    }


}

1 个答案:

答案 0 :(得分:1)

好的,这是我的评估:

TL; DR

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

说明

这是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);设置选择,是否已完成异步调用。我忘了这是否应该抛出异常。

现在转到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());
        }
    });
}
  • 如果要动态更新微调器的元素,还应包括更新(添加,删除或更新)适配器中List元素的方法。
  • 就像我之前提到的那样,将听众放在AsyncTask中虽然可能适用,但却不是一个好习惯。更不用说你也试图改变UI(设置TextView值)。这将产生错误,因为您的调用不在UI线程上。这就是为什么我说你应该把AsyncTask集中在获取数据上

假设您有自己的自定义适配器,这是我的自定义适配器,它能够处理数据更新:

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();
    }
}

当然,这只是一个例子。

摘要

尝试更新您的代码,如下所示:

//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);
    }
}

希望这有帮助!