«

Android HandlerThread 实例

时间:2024-3-2 19:41     作者:韩俊     分类: Android


关于Handler的基础知识 Handler 详解 中提及了带有Looper的Thread,平时开发中我们只要简单的带有Looper的线程即可,而Android中已经为我们提供了这么一个Thread,那就是HandlerThread,我们先来简单的看一下这个类:

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason is isAlive() returns false, this method will return null. If this thread 
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    /**
     * Quits the handler thread's looper.
     * <p>
     * Causes the handler thread's looper to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     *
     * @see #quitSafely
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    /**
     * Quits the handler thread's looper safely.
     * <p>
     * Causes the handler thread's looper to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * Pending delayed messages with due times in the future will not be delivered.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p>
     * If the thread has not been started or has finished (that is if
     * {@link #getLooper} returns null), then false is returned.
     * Otherwise the looper is asked to quit and true is returned.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     */
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

代码除了注释没有几行,最主要的是在run方法中准备Looper的部分,当然还有同步的操作。接下来我们用Server结合HandlerThread模拟一个后台加载耗时操作的Demo。

声明Service

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="studio.neulion.com.tasktest">
    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
        <activity
                android:name="studio.neulion.com.tasktest.ServerActivity"
                android:launchMode="singleTask">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        <service android:name=".CommonServer" />
    </application>
</manifest>

实现Service类

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class CommonServer extends Service
{
    private ServiceHandler mServiceHandler;

    private final class ServiceHandler extends Handler
    {
        public ServiceHandler(Looper looper)
        {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg)
        {
            super.handleMessage(msg);
            /*
            *这里执行到了位于HandlerThread子线程中的方法,一般是耗时的操作
             */
            Log.d(ServerActivity.TAG, "HandlerThread_handleMessage: " + Thread.currentThread().getId());

            long endTime = System.currentTimeMillis() + 5 * 1000;

            while (System.currentTimeMillis() < endTime)
            {
                synchronized (this)
                {
                    try
                    {
                        wait(endTime - System.currentTimeMillis());
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            }

            stopSelf(msg.arg1);
        }
    }

    @Override
    public void onCreate()
    {
        super.onCreate();

        /*
        *直接获取带有Looper的子线程,HandlerThread是Android提供的带有Looper的子线程,这里通过UI线程向该HandlerThread线程发送消息
        *以期完成UI线程和子线程之间的通信
         */
        HandlerThread thread = new HandlerThread("ServiceStartArguments", android.os.Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        Looper serviceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(serviceLooper);

        Log.i(ServerActivity.TAG, "CommonServer_onCreate");

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.i(ServerActivity.TAG, "CommonServer_onStartCommand");

        /*
        *通过UI线程向子线程发送消息,这个时候会在恰当的时机调用ServiceHandler的handleMessage()方法
         */
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        return null;
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();

        Log.i(ServerActivity.TAG, "CommonServer_onDestroy");
    }
}

定义UI

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/start_server"
            android:text="Start" />

</LinearLayout>

测试用例

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

public class ServerActivity extends Activity
{
    public static final String TAG = "StartServer";

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_start_server);

        initView();
    }

    private void initView()
    {
        final View startView = findViewById(R.id.start_server);

        if (startView != null)
        {
            startView.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    Intent intent = new Intent(ServerActivity.this, CommonServer.class);
                    startService(intent);
                }
            });
        }
    }
}

测试结果

生命周期如下:

onCreate() —>> onStartCommond —–>> handleMessage —->>onDestroy

当然下次再启动service,就不会再执行onCreate()方法了。

        <p>版权声明:本文为博主原创文章,未经博主允许不得转载。</p>

标签: android

热门推荐