Android---手动创建线程与GUI线程同步(一)

本文介绍了如何在Android应用中创建和管理子线程,并通过Handler实现UI更新,确保线程安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽然使用Intent Service 和创建AsyncTasks是非常有用的捷径,但还是有一些需要创建和管理自己的线程来执行后台处理的场景。通常的情况就是存在长时间运行或者相互联系的线程,它们需要一些比目前两种技术描述的更加微秒或者复杂的管理操作。

这里我们将介绍如何创建和启动新的Thread对象,以及如何在更新UI前与GUI线程同步。

可以使用Android的Handler类与java.lang.Thread中提供的线程类创建和管理子线程。

代码清单如下:

1>布局如下

1.1>效果


1.2>代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.cxc.threadandhandler.MainActivity" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Thread用于耗时任务 + Handler用于GUI同步" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/show_info_tv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="显示后台任务情况" />

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

</LinearLayout>


2>代码如下

2.1>详细代码如下:

package com.demo.cxc.threadhandlerdemo;

import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private TextView show_info_tv;
    private Button start_task_bt;

    /*

    //在主线程上初始化一个handler
    //每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程)
    //Handler对象初始化后,就默认与对它初始化的进程的消息队列绑定
    //在这里myHandler与GUI线程(主线程)的消息队列绑定

     */

    private Handler myHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "---onCreate---Thread id:" + Thread.currentThread().getId());
        initViews();
    }

    private void initViews() {
        Log.d(TAG, "---initViews---thread id:" + Thread.currentThread().getId());
        show_info_tv = (TextView) findViewById(R.id.show_info_tv);
        start_task_bt = (Button) findViewById(R.id.start_task_bt);

        start_task_bt.setOnClickListener(myButtonClickListener);

    }

    View.OnClickListener myButtonClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
                case R.id.start_task_bt:
                    // to-do
                    // 将耗时的操作移到子线程中
                    Log.d(TAG, "---Start Task Button Click---");
                    Thread myThread = new Thread(null,
                            doBackgroundThreadProcessingRunnable, "background");
                    myThread.start();
                    break;
                default:
                    break;
            }

        }
    };

    // 执行后台处理方法的Runnable
    private Runnable doBackgroundThreadProcessingRunnable = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            Log.d(TAG, "---doBackgroundThreadProcessingRunnable run---thread id :" + Thread.currentThread().getId());
            backgroundThreadProcessing();
        }
    };

    // 在后台执行一些处理的方法---耗时操作
    private void backgroundThreadProcessing() {
        // to-do 耗时操作
        for (int i = 0; i < 10; i++) {

            Log.d(TAG, "*****thread id :" + Thread.currentThread().getId() + "---backgroundThreadProcessing---i:" + i);
            // 当前线程休眠1000ms
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            // 在UI主线程上使用Handler发布doUpdateGUI Runnable
            /*
            * doUpdateGUIRunnable对象并没有新建一个单独的线程,
            * 而是运行在myHandler所在的线程中,
            * 在这里就是GUI线程中
            * */
            myHandler.post(doUpdateGUIRunnable);

        }

    }

    // 执行updateGUI方法的Runnable
    private Runnable doUpdateGUIRunnable = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            Log.d(TAG, "++++++doUpdateGUIRunnable run---thread id :" + Thread.currentThread().getId());
            updateGUI();

        }
    };

    // 这个方法必须由UI线程调用
    private void updateGUI() {
        // to-do 更新UI
        show_info_tv.setText(show_info_tv.getText().toString() + "¥¥");
    }


}



2.2>运行效果:


2.3> Log输出如下:

06-04 15:52:12.949  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ---onCreate---Thread id:1
06-04 15:52:12.949  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ---initViews---thread id:1
06-04 15:52:19.829  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ---Start Task Button Click---
06-04 15:52:19.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ---doBackgroundThreadProcessingRunnable run---thread id :14444
06-04 15:52:19.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:0
06-04 15:52:20.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:1
06-04 15:52:20.829  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:21.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:2
06-04 15:52:21.829  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:22.834  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:3
06-04 15:52:22.834  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:23.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:4
06-04 15:52:23.829  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:24.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:5
06-04 15:52:24.829  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:25.829  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:6
06-04 15:52:25.834  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:26.834  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:7
06-04 15:52:26.834  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:27.834  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:8
06-04 15:52:27.839  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:28.834  27514-28040/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ *****thread id :14444---backgroundThreadProcessing---i:9
06-04 15:52:28.834  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1
06-04 15:52:29.839  27514-27514/com.demo.cxc.threadhandlerdemo D/MainActivity﹕ ++++++doUpdateGUIRunnable run---thread id :1

从以上Log 可以看出,doUpdateGUIRunnable确定是运行在GUI线程中,即myHandler.post(doUpdateGUIRunnable)会使doUpdateGUIRunable对象运行在创建myHandler的线程中,在这里也就是GUI线程中了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值