【深圳孕期吃即食燕窝溯源码】【apktool源码github】【atlaux 源码下载】android计时器源码_安卓计时器app源代码

时间:2024-11-28 18:24:07 分类:饭卡源码 来源:测试指标源码正确率

1.android中looper的实现原理,为什么调用looper.prepare就在当前线程关联了一个lo

android计时器源码_安卓计时器app源代码

android中looper的实现原理,为什么调用looper.prepare就在当前线程关联了一个lo

       å®žé™…上:消息发送和计划任务提交之后,它们都会进入某线程的消息队列中,我们可以把这个线程称之为目标线程。不论是主线程还是子线程都可以成为目标线程。上例中之所以在主线程中处理消息,是因为我们要更新UI,按照android中的规定我们必须由主线程更新UI。所以我们让主线程成为了目标线程。

       é‚£ä¹ˆå¦‚何控制让某个线程成为目标线程呢?

       è¿™å°±å¼•å‡ºäº†Looper的概念。Android系统中实现了消息循环机制,Android的消息循环是针对线程的,每个线程都可以有自己的消息队列和消息循环。Android系统中的通过Looper帮助线程维护着一个消息队列和消息循环。通过Looper.myLooper()得到当前线程的Looper对象,通过Looper.getMainLooper()得到当前进程的主线程的Looper对象。

       å‰é¢æåˆ°æ¯ä¸ªçº¿ç¨‹éƒ½å¯ä»¥æœ‰è‡ªå·±çš„消息队列和消息循环,然而我们自己创建的线程默认是没有消息队列和消息循环的(及Looper),要想让一个线程具有消息处理机制我们应该在线程中先调用Looper.prepare()来创建一个Looper对象,然后调用Looper.loop()进入消息循环。如上面的源码所示。

       å½“我们用Handler的构造方法创建Handler对象时,指定handler对象与哪个具有消息处理机制的线程(具有Looper的线程)相关联,这个线程就成了目标线程,可以接受消息和计划任务了。Handler中的构造方法如下:

       [java] view

       plaincopyprint?计计深圳孕期吃即食燕窝溯源码

       public Handler() {

        if (FIND_POTENTIAL_LEAKS) {

        final Class<? extends Handler> klass = getClass();

        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

        (klass.getModifiers() & Modifier.STATIC) == 0) {

        Log.w(TAG, "The following Handler class should be static or leaks might occur: " +

        klass.getCanonicalName());

        }

        }

       mLooper = Looper.myLooper();

        if (mLooper == null) {

        throw new RuntimeException(

        "Can't create handler inside thread that has not called Looper.prepare()");

        }

        mQueue = mLooper.mQueue;

        mCallback = null;

        }

       public Handler(Looper looper) {

        mLooper = looper;

        mQueue = looper.mQueue;

        mCallback = null;

        }

       public Handler() {

        if (FIND_POTENTIAL_LEAKS) {

        final Class<? extends Handler> klass = getClass();

        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

        (klass.getModifiers() & Modifier.STATIC) == 0) {

        Log.w(TAG, "The following Handler class should be static or leaks might occur: " +

        klass.getCanonicalName());

        }

        }

        mLooper = Looper.myLooper();

        if (mLooper == null) {

        throw new RuntimeException(

        "Can't create handler inside thread that has not called Looper.prepare()");

        }

        mQueue = mLooper.mQueue;

        mCallback = null;

        }

        public Handler(Looper looper) {

        mLooper = looper;

        mQueue = looper.mQueue;

        mCallback = null;

        }

       åœ¨ä¸Šè¿°çš„计时器的例子中,之所以可以在主线程中处理消息而我们自己并没有调用Looper.prepare()等方法,是因为Android系统在Activity启动时为其创建一个消息队列和消息循环,当我们用无参的Handler构造方法创建对象时又用了当前线程的Looper对象,及将handler与主线程中的Looper对象进行了关联。

       android中是使用Looper机制来完成消息循环的,但每次创建线程时都先初始化Looper比较麻烦,因此Android为我们提供了一个HandlerThread类,他封装了Looper对象,是我们不用关心Looper的开启和释放问题。

       ä¸ç®¡æ˜¯ä¸»çº¿ç¨‹è¿˜æ˜¯å…¶ä»–线程只要有Looper的线程,别的线程就可以向这个线程的消息队列中发送消息和任务。

       æˆ‘们使用HandlerThread类代替上一篇文章中的子线程,并用HandlerThread类中的Looper对象构造Handler,则接受消息的目标线程就不是主线程了,而是HandlerThread线程。代码如下:

       [java] view

       plaincopyprint?

       public class clockActivity extends Activity {

        /** Called when the activity is first created. */

        private String TAG="clockActivity";

        private Button endButton;

        private TextView textView;

        private int timer=0;

        private boolean isRunning=true;

        private Handler handler;

        @Override

        public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        endButton=(Button)findViewById(R.id.endBtn);

        textView=(TextView)findViewById(R.id.textview);

        endButton.setOnClickListener(new View.OnClickListener() {

        @Override

        public void onClick(View v) {

        // TODO Auto-generated method stub

       isRunning=false;

        }

        });

        HandlerThread thread=new HandlerThread("myThread");

        handler=new Handler(thread.getLooper());//与HandlerThread中的Looper对象关联

        thread.start();

        Runnable r=new Runnable(){

       @Override

        public void run() {

        // TODO Auto-generated method stub

       if(isRunning){

        textView.setText("走了"+timer+"秒");

        timer++;

        handler.postDelayed(this, );//提交任务r,延时1秒执行

       }

        }

        };

        handler.postDelayed(r, );

        }

       }

       ã€€ã€€public class clockActivity extends Activity {

        /** Called when the activity is first created. */

        private String TAG="clockActivity";

        private Button endButton;

        private TextView textView;

        private int timer=0;

        private boolean isRunning=true;

        private Handler handler;

        @Override

        public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        endButton=(Button)findViewById(R.id.endBtn);

        textView=(TextView)findViewById(R.id.textview);

        endButton.setOnClickListener(new View.OnClickListener() {

        @Override

        public void onClick(View v) {

        // TODO Auto-generated method stub

        isRunning=false;

        }

        });

        HandlerThread thread=new HandlerThread("myThread");

        handler=new Handler(thread.getLooper());//与HandlerThread中的Looper对象关联

        thread.start();

        Runnable r=new Runnable(){

        @Override

        public void run() {

        // TODO Auto-generated method stub

        if(isRunning){

        textView.setText("走了"+timer+"秒");

        timer++;

        handler.postDelayed(this, );//提交任务r,延时1秒执行

        }

        }

        };

        handler.postDelayed(r, );

        }

       }

       ã€€ã€€æ­¤æ—¶å¤„理任务会在handlerThread线程中完成。当然这个例子会出线异常:依然是因为在非主线程中更新了UI。这样做只是为了大家能够理解这种机制。

       ã€€ã€€æ·±å…¥ç†è§£Android消息处理机制对于应用程序开发非常重要,也可以让我们对线程同步有更加深刻的认识,希望这篇文章可以对朋友们有所帮助。