请解释一下为什么这段代码不起作用?(我需要在 onClick()中调用 lv.setAdapter(adapterA)。有必要更改适配器)。它可以在主线程上运行代码,但我需要在另一个线程中加载数据。我会很感激任何想法。谢谢。
package com.example.examplelist;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
public class ActivityElemsExample extends Activity implements OnClickListener {
ArrayList<Elem> myList;
Button btn;
ListView lv;
AdapterA adapterA;
AdapterB adapterB;
boolean running = false;
Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.button_loading);
btn.setOnClickListener(this);
lv = (ListView)findViewById(R.id.lv);
myList = new ArrayList<Elem>();
adapterA = new AdapterA(this, myList);
adapterB = new AdapterB(this, myList);
}
public void onClick(View button){
if(!running){
running = true;
Log.d("MyLogs", "LOADING");
/*
if(...){
lv.setAdapter(adapterA);
}
else{
lv.setAdapter(adapterB);
}
*/
lv.setAdapter(adapterA);
thread = new Thread(new Runnable(){
public void run(){
myList.clear();
for(int i=0; i < 3000; i++){
myList.add(new Elem(i, System.currentTimeMillis(), "Elem "+i));
}
handler.sendEmptyMessage(1);
}
});
thread.start();
}
}
public void onDestroy(){
super.onDestroy();
if(thread != null){
while(true){
try{
thread.join();
break;
}
catch (InterruptedException e){}
}
}
}
public Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
/*
if(...){
}
else{
}
*/
adapterA.notifyDataSetInvalidated();
adapterA.notifyDataSetChanged();
running = false;
}
};
}
日志:
FATAL EXCEPTION: main
Process: com.example.examplelist, PID:553
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its contentges ...
答案 0 :(得分:0)
问题是,您在显示适配器的数据时正在修改它。您应该在添加更多项目之前复制数据,然后替换适配器中的数据并通知。
答案 1 :(得分:0)
您可以从后台线程在UI线程上运行该段代码。任何修改UI的工作(例如列表)都需要在UI线程上。您可以使用活动的runOnUiThread方法。
MyActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
// UI work here
}
});
您还可以将所有项目放在后台线程的列表中,然后在列表中包含所有项目后更新适配器。
http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
答案 2 :(得分:-1)
解决方案:
package com.example.examplelist;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
public class ActivityElemsExample extends Activity implements OnClickListener {
ArrayList<Elem> myList;
Button btn;
ListView lv;
AdapterA adapterA;
AdapterB adapterB;
boolean running = false;
Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.button_loading);
btn.setOnClickListener(this);
lv = (ListView)findViewById(R.id.lv);
myList = new ArrayList<Elem>();
adapterA = new AdapterA(this, myList);
adapterB = new AdapterB(this, myList);
}
public void onClick(View button){
if(!running){
running = true;
Log.d("MyLogs", "LOADING");
thread = new Thread(new Runnable(){
public void run(){
myList.clear();
for(int i=0; i < 3000; i++){
myList.add(new Elem(i, System.currentTimeMillis(), "Elem "+i));
}
handler.sendEmptyMessage(1);
}
});
thread.start();
}
}
public void onDestroy(){
super.onDestroy();
if(thread != null){
while(true){
try{
thread.join();
break;
}
catch (InterruptedException e){}
}
}
}
public Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
lv.setAdapter(adapterA);
running = false;
}
};
}