9

我在一个非常基本的处理程序教程中遇到了这段代码。代码工作正常,但我不明白为什么我必须使用 Handler progressDialog.dismiss()???我删除了 Handler 部分并放入 progressDialog.dismiss()方法中run(),它工作正常。那为什么要用Handler???

 import android.app.Activity;
    import android.app.ProgressDialog;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.Toast;


    public class HandlerThread extends Activity{

    private Button start;
    private ProgressDialog progressDialog;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        start = (Button) findViewById(R.id.Button01);
        start.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                fetchData();
            }

        });
    }



    protected void fetchData() {
        // TODO Auto-generated method stub
        progressDialog = ProgressDialog.show(this, "", "Doing...");
        new Thread() {
            public void run() {
                try {

                    Thread.sleep(8000);

                    } catch (InterruptedException e) {

                    }
                      messageHandler.sendEmptyMessage(0);

                    }
        }.start();


    }



    private Handler messageHandler = new Handler() {

        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            progressDialog.dismiss();

        }
    };
}
4

4 回答 4

32

为什么要在 Android 中使用 Handler?


首先:让我们知道什么是线程:

  • 线程有助于多任务处理
  • 线程可以作为在主进程下运行的迷你进程进行教学
  • 线程至少可以实现并行执行

第二:让我们知道应用程序线程:-

  • 当 android 应用程序第一次启动时,运行时系统会创建一个主线程,这个主线程将负责执行 android 中的所有组件

Android UI-Toolkit 不是线程安全的

  • 如前所述,android主线程中有许多组件,现在假设其中一个组件需要很长时间才能执行,那么这会使主线程无响应,并且会显示应用程序无响应
  • 子线程不能直接操作android中的应用程序(主)线程
  • Handler作为一个接口,收集来自子线程的消息,并随着消息的到达,一一更新主应用线程,线程处理程序在主线程中实现。

处理程序类:

  • 出于多线程的目的,我们将使用来自包的处理程序类android.os.Handler
  • 每个线程由处理程序类的一个实例处理

数字

  • 从上图中我们可以看出,每个线程都由一个Handler类的实例来处理
  • 线程在消息的帮助下相互通信
  • 这个处理程序类通过允许它们一起运行实现多线程来帮助维护一种同步协调黑白线程

制作处理程序的实例

Handler handlerObject = new Handler();

使用处理程序的最后一块是使用 Runnable 接口:

  • handler类利用runnable接口实现多线程
  • 我们重写 run 方法以执行线程指定次数

Class NameOfClass implements Runnable
{
    Public void run()
    {
        //Body of run method
    }
}

把所有的放在一起

//Create handler in the thread it should be associated with 
//in this case the UI thread
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
    public void run() {
        while(running){
            //Do time consuming stuff

            //The handler schedules the new runnable on the UI thread
            handler.post(new Runnable() {
                //Ex.. using progressbar to set the pogress
                            //Updating the UI is done inside the Handler
            });
        }
    }
};
new Thread(runnable).start();
于 2013-08-15T04:03:16.063 回答
19

从以下文档View

在任何视图上调用任何方法时,您必须始终在 UI 线程上。如果您在其他线程上工作并希望从该线程更新视图的状态,您应该使用Handler.

在您的示例中,当您必须根据上述文档调用 上的dismiss()方法时,您必须从 UI 线程执行此操作。ProgressDialog当类被实例化时(大概在 UI 线程上) ,messageHandler被初始化为 a 的一个实例。HandlerHandlerThread

从以下文档Handler

每个Handler实例都与单个线程和该线程的消息队列相关联。当您创建一个 newHandler时,它会绑定到创建它的线程的线程/消息队列——从那时起,它会将消息和可运行对象传递到该消息队列并在它们从消息队列中出来时执行它们.

因此,要从新线程与 UI 线程进行通信,只需向HandlerUI 线程上创建的消息发布消息。

如果您View从 UI 线程外部调用 a 上的方法,它会调用未定义的行为,这意味着它可能看起来工作正常。但并不总是保证能正常工作。

于 2012-09-07T06:43:19.253 回答
6

越容易越好。您可以尝试使用以下代码,而不是使用处理程序:

runOnUiThread(
    new Runnable() { 
        public void run() 
        { 

        //Update user interface here

        } 
    }
);

不要让你的生活变得复杂;)

于 2013-08-16T05:09:56.520 回答
2

当应用程序启动时,android 系统会启动一个具有主线程的进程,该主线程负责处理 UI 渲染和事件。Android UI 不是线程安全的,所以我们只能通过 Event 线程访问 android UI。在您的程序中,您通过以下代码块定义了另一个线程而不是事件:

 new Thread() {
        public void run() {
            try {

                Thread.sleep(8000);

                } catch (InterruptedException e) {

                }
                  messageHandler.sendEmptyMessage(0);

                }
    }.start();

现在,如果您想关闭进度对话框,您只能在事件线程中执行此操作。处理程序用于处理/处理消息队列的消息。处理程序与一个线程相关联,在您的情况下,它是事件线程,因为默认情况下它将与正在创建它的线程相关联。通过 messageHandler.sendEmptyMessage() 另一个线程向处理程序发送消息,处理程序在 handleMessage 方法中处理此消息。

于 2012-09-07T06:45:19.543 回答