Обновить пользовательский интерфейс из события с потоком - PullRequest
0 голосов
/ 26 марта 2010

Я работаю над небольшим приложением, чтобы опробовать идею, которая у меня есть. Идея состоит в том, чтобы периодически обновлять пользовательский интерфейс, когда происходит какое-либо событие. В созданной мной демонстрации я обновляю ProgressDialog каждые 2 секунды в течение 15 ходов.

Проблема, с которой я столкнулся, которую я не совсем понимаю, заключается в том, что при обработке события я отправляю сообщение обработчику, который должен обновить сообщение в ProgressDialog. Однако когда это происходит, я получаю исключение, в котором говорится, что я не могу обновить пользовательский интерфейс из этого потока.

В моей активности отображается следующий код:

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

Я что-то упустил? Логика имеет смысл для меня, и похоже, что все должно работать, я использую обработчик для обновления пользовательского интерфейса, как это рекомендуется.

Любая помощь будет оценена.

Спасибо, Тайрон

P.S. Я разрабатываю для Android 1.5

1 Ответ

0 голосов
/ 26 марта 2010

Я нашел проблему. После сравнения моего кода с чужим кодом, который был очень похож, была обнаружена следующая небольшая проблема:

обработчик handleMessage * +1005 * (handler.obtainMessage (MESSAGE_RECEIVE_COMPLETED));.

На самом деле должно быть:

1012 * Обработчик * SendMessage (handler.obtainMessage (MESSAGE_RECEIVE_COMPLETED));.

Надеюсь, кто-то найдет это полезным и узнает из моей ошибки:)

С уважением, Тайрон

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...