此问题已经在这里有了答案:
我在尝试自动更新Android活动中的视图时遇到了一些麻烦。该应用程序显示一些消息,例如聊天。我正在使用ListView将消息与ArrayAdapter一起放置。
我使用此方法来更新ListView
public void loadMessages() {
ArrayList<String> messages = this.dbHelper.getMessages();
conversationArrayAdapter.clear();
conversationArrayAdapter.addAll(messages);
conversationArrayAdapter.notifyDataSetChanged();
}
我的想法是放置一个调用该方法的线程,但是当我尝试执行此操作时,出现以下错误。
仅创建视图层次结构的原始线程可以触摸其视图。
UI应该仅从UI(主)线程进行更新。这是使用AsyncTask的解决方案。
public void asyncCallWithSchedule() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new SearchAsync().execute(txtSearch.getText().toString());
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 2000);
}
}
AsyncTask类:
private class SearchAsync extends
AsyncTask < String, Object, List < Users >> {
@Override
protected List < Users > doInBackground(String...params) {
// Call DB here
return null;
}
@Override
protected void onPostExecute(List < Users > result) {
super.onPostExecute(result);
// Update UI here
}
}
因为您正尝试从Thread访问或更新UI元素。为避免此错误,您将需要使用runOnUiThread从Thread更新UI,如下所示:
Your_Current_Activity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// Update UI here
loadMessages();
}
});
第二种解决方法是使用AsyncTask而不是线程
使用此代码。
public class MainActivity extends Activity
{
private Timer autoUpdate;
@Override
public void onResume()
{
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask()
{
@Override
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
updateScore();
}
});
}
}, 0, 5000); // updates each 5 seconds
}
@Override
public void onPause()
{
autoUpdate.cancel();
super.onPause();
}
@Override
public void onCreate(Bundle savedInstanceState)
{
// initialize view layout
super.onCreate(savedInstanceState);
setContentView(R.layout.cleanermain);
super.onResume();
}
private void updateScore()
{
// decide output
// update cricket score
}
}
简单:
public void loadMessages() {
ArrayList<String> messages = this.dbHelper.getMessages();
conversationArrayAdapter.clear();
conversationArrayAdapter.addAll(messages);
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
conversationArrayAdapter.notifyDataSetChanged();
}
});
}