当前位置:   article > 正文

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

android native开发

目的

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(); // 直接启动方式
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述

Runnable

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

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

Thread t = new Thread(new MyRunnable());
t.start(); // 创建新线程,线程启动后会运行其中run方法
// new MyThread().start(); // 直接启动方式
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

// 匿名内部类方式
Thread t = new Thread(new Runnable(){
    public void run() {
        // TODO
    }
});
t.start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

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); // 每两秒触发一次定时器子线程
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

在这里插入图片描述

上面演示中子线程可以创建 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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

AsyncTask

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

总结

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/141804
推荐阅读
相关标签
  

闽ICP备14008679号