您好我已经在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);
}
}
答案 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());
}
});
}
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);
}
}
希望这有帮助!