【问题标题】:Update UI from an event with a thread使用线程从事件更新 UI
【发布时间】:2010-03-26 08:48:52
【问题描述】:

我正在开发一个小型应用程序来尝试我的想法。这个想法是在发生某种事件时定期更新 UI。在我创建的演示中,我每 2 秒更新一次 ProgressDialog,持续 15 圈。

我遇到的问题是,我不太明白,当一个事件被处理时,我会向处理程序发送一条消息,该处理程序应该更新 ProgressDialog 中的消息。但是,当这种情况发生时,我会收到一个异常,指出我无法从该线程更新 UI。

以下代码出现在我的 Activity 中:

ProgressDialog diag;
String diagMessage = "Started loading...";

final static int MESSAGE_DATA_RECEIVED = 0;
final static int MESSAGE_RECEIVE_COMPLETED = 1;


final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        diag.setMessage(diagMessage);

        switch(msg.what){
            case MESSAGE_DATA_RECEIVED:

                break;
            case MESSAGE_RECEIVE_COMPLETED:
                dismissDialog();
                killDialog();
                break;
        }
    }
};

Boolean isRunning = false;

/**
 * Called when the activity is first created.
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setupDialog();
    if(isRunning){
        showDialog();
    }

    setContentView(R.layout.main);


}

void setupDialog(){
    if(diag == null){
        diag = new ProgressDialog(ThreadLoading.this);
        diag.setMessage(diagMessage);
    }
}

void showDialog(){
    isRunning = true;
    if(diag != null && !diag.isShowing()){
        diag.show();
    }
}

void dismissDialog(){
    if(diag != null && diag.isShowing()){
        diag.dismiss();
    }
}

void killDialog(){
    isRunning = false;
}

public void onStart(){
    super.onStart();

    showDialog();



    Thread background = new Thread(new Runnable(){
        public void run(){
            try{
                final ThreadRunner tr = new ThreadRunner();
                tr.setOnDataReceivedListener(new ThreadRunner.OnDataReceivedListener(){
                    public void onDataReceived(String message){
                        diagMessage = message;
                        handler.handleMessage(handler.obtainMessage(MESSAGE_DATA_RECEIVED));
                    }
                });

                tr.setOnDataDownloadCompletedEventListener(new ThreadRunner.OnDataDownloadCompletedListener(){
                    public void onDataDownloadCompleted(String message){
                        diagMessage = message;
                        handler.handleMessage(handler.obtainMessage(MESSAGE_RECEIVE_COMPLETED));
                    }
                });

                tr.runProcess();
            }
            catch(Throwable t){
                throw new RuntimeException(t);
            }
        }
    });

    background.start();
}

@Override
public void onPause(){
    super.onPause();
    dismissDialog();
}

出于好奇,这里是 ThreadRunner 类的代码:

public interface OnDataReceivedListener {
    public void onDataReceived(String message);
}

public interface OnDataDownloadCompletedListener {
    public void onDataDownloadCompleted(String message);
}

private OnDataReceivedListener onDataReceivedEventListener;
private OnDataDownloadCompletedListener onDataDownloadCompletedEventListener;


int maxLoop = 15;
int loopCount = 0;
int sleepTime = 2000;

public void setOnDataReceivedListener(OnDataReceivedListener onDataReceivedListener){
    this.onDataReceivedEventListener = onDataReceivedListener;
}

public void setOnDataDownloadCompletedEventListener(OnDataDownloadCompletedListener onDataDownloadCompletedListener){
    this.onDataDownloadCompletedEventListener = onDataDownloadCompletedListener;
}

public void runProcess(){
    for(loopCount = 0; loopCount < maxLoop; loopCount++){
        try{
            Thread.sleep(sleepTime);
            onDataReceivedEventListener.onDataReceived(Integer.toString(loopCount));
        }
        catch(Throwable t){
            throw new RuntimeException(t);
        }
    }

    onDataDownloadCompletedEventListener.onDataDownloadCompleted("Download is completed");
}

我错过了什么吗?这个逻辑对我来说很有意义,看起来一切都应该正常工作,我正在使用处理程序来更新 UI,就像推荐的那样。

任何帮助将不胜感激。

谢谢, 泰隆

附:我正在为 Android 1.5 开发

【问题讨论】:

  • 有空的时候看看AsynTask类;它使线程变得无痛(以失去一些控制为代价)
  • 谢谢,我之前简要地看了一下,但没有深入研究它。基本上我想要做的,不是用这段代码,是有一个 ListView 一次加载大约 3 / 4 个项目。类似于 Market 应用程序。

标签: android


【解决方案1】:

我发现了问题。我的代码和别人的代码非常相似,对比后发现如下小问题:

handler.handleMessage(handler.obtainMessage(MESSAGE_RECEIVE_COMPLETED));

实际上应该是:

handler.sendMessage(handler.obtainMessage(MESSAGE_RECEIVE_COMPLETED));

希望有人发现这很有用并从我的错误中吸取教训:)

问候, 泰隆

【讨论】:

    猜你喜欢
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多