Android Native APP开发笔记:多线程编程

Posted Naisu Xu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Native APP开发笔记:多线程编程相关的知识,希望对你有一定的参考价值。

文章目录

目的

android中UI线程对于开发者和用户来说都是最主要接触到的线程。一般来说为了UI流畅、不卡顿,耗时操作是不推荐放在UI线程中的。但是耗时操作的需求又是存在的,这时候就需要用到多线程编程了,新建一条子线程去处理耗时操作。这篇文章将对相关内容进行简单介绍。

Java中的多线程

Android应用大部分都是用Java开发的,所以Java中的一些多线程编程方式在Android里也是可以使用的。

Thread

这是最基本的多线程操作:

// 定义继承自Thread的类
class MyThread extends Thread 
    // 重写run方法
    public void run() 
        // TODO
    


MyThread t = new MyThread();
t.start(); // 创建新线程并启动,线程启动后会运行其中run方法
// new MyThread().start(); // 直接启动方式

Runnable

前面用的是继承的方式,只能继承一个类,所以更加常见的是使用下面这种方式:

// 定义类来实现Runnable接口
class MyRunnable implements Runnable 
    // 实现接口中的run方法
    public void run() 
        // TODO
    


Thread t = new Thread(new MyRunnable());
t.start(); // 创建新线程,线程启动后会运行其中run方法
// new MyThread().start(); // 直接启动方式

很多时候也可以直接使用匿名内部类方式:

// 匿名内部类方式
Thread t = new Thread(new Runnable()
    public void run() 
        // TODO
    
);
t.start();

Timer

上面演示中在子线程中每隔1000ms执行一次操作,如果只是需要这种定时任务的话使用定时器更加方便些:

// import java.util.Timer;
// import java.util.TimerTask;

Timer timer = new Timer(); // Timer用来调度运行TimerTask对象
// 一个Timer可以调度多个TimerTask

TimerTask task = new TimerTask() 
    public void run() 
        // TODO
    
;

// timer.schedule(task, 2000); // 延迟2000ms后运行一次task
timer.schedule(task, 2000, 1000); // 延迟2000ms后运行一次task,然后每隔1000ms重复运行task

Android中的多线程

Android中子线程是不能更新UI的,但很多时候又需要子线程处理一些耗时操作,然后根据操作结果来更新UI。针对这个业务需求Android中又提供了一些多线程机制。

Handler

Handler本身并不是多线程,它只是提供一种机制,使一个线程可以发送消息给另一个线程,通常默认情况下就是子线程发送消息给UI线程,这样UI线程就可以根据接收到的消息来做对应的处理,比如更新UI元素等。

Handler通常和前面Java的多线程方式结合使用。下面是个简单的演示:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity 

    // 声明Handler对象并重写handleMessage方法
    @SuppressLint("HandlerLeak")
    private final Handler handler = new Handler() 
        @Override
        public void handleMessage(Message msg)  // 收到消息时会触发handleMessage方法
                                                 // 这个Handler对象在哪个线程,handleMessage方法就在哪个线程执行
            TextView text = findViewById(R.id.text);
            text.setText(msg.obj.toString());
        
    ;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Timer().schedule(new TimerTask() 
            public void run() 
                Message message = new Message(); // 新建消息
                message.obj = new Date(System.currentTimeMillis()); // 填充消息内容
                handler.sendMessage(message); // 发送消息
            
        , 2000, 2000); // 每两秒触发一次定时器子线程
    

上面演示中子线程可以创建 Message 对象,这个对象中可以保存 obj 等很多东西。通过 Handler 对象的一些方法,比如上面 sendMessage() 方法可以将 Message 发送给 Handler 所在线程。在 Handler 所在线程中会有 MessageQueue 用来接收这些 Message ,还有 Looper 进行消息处理,最终调用 Handler 对象的 handleMessage() 方法。在UI线程中 MessageQueueLooper 默认都会自动创建的。

现在的Android版本中上面这样的使用方式会被认为可能引起Activity泄漏,可以改用下面方式:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity 

    private static class MyHandler extends Handler 

        //弱引用持有MainActivity , GC 回收时会被回收掉
        private final WeakReference<MainActivity> weakReference;

        public MyHandler(MainActivity activity) 
            this.weakReference = new WeakReference(activity);
        

        @Override
        public void handleMessage(Message msg) 
            MainActivity activity = weakReference.get();
            if (activity != null) 
                TextView text = activity.findViewById(R.id.text);
                text.setText(msg.obj.toString());
            
        
    

    private final MyHandler myHandler = new MyHandler(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Timer().schedule(new TimerTask() 
            public void run() 
                Message message = new Message();
                message.obj = new Date(System.currentTimeMillis());
                myHandler.sendMessage(message);
            
        , 2000, 2000);
    

AsyncTask

AsyncTask是Android另一个用来异步更新UI的方式,现在(API level 30,Android 11)已被弃用,这里就不再进行介绍了。

总结

多线程的基础操作是比较简单的,相对复杂的线程间同步互斥等的问题先不在这里展开,使用时注意下不同线程对同一个资源操作的问题即可。

以上是关于Android Native APP开发笔记:多线程编程的主要内容,如果未能解决你的问题,请参考以下文章

Android Native APP开发笔记:从新建到打包流程记录

Android Native APP开发笔记:使用WebView控件加载网页

Android Native APP开发笔记:双击返回键退出应用&单击返回键返回桌面

react native android 开发,基础配置笔记。

React Native笔记

React Native学习笔记——配置开发环境