在Android项目中,有经验的开发人员都知道,一些耗时的IO操作等都必须在子线程中去操作,那么可以有哪些方法来开启子线程呢,一般可以使用Java中自带的几种方法,也可以使用Andorid特有的一些类。

用Java来实现异步

主要有两种方法来实现异步,继承Thread类和实现Runnable接口

1.继承Thread类

先上代码

public class MyThread extends Thread {

    private String name;

    public MyThread(String name){
this.name = name;
} @Override
public void run() {
System.out.println(name);
}
}
public class MainTest { public static void main(String[] args){ MyThread myThread1 = new MyThread("myThread1");
MyThread myThread2 = new MyThread("myThread2");
MyThread myThread3 = new MyThread("myThread3"); myThread1.start();
myThread2.start();
myThread3.start();
}
}

MyThread继承自Thread类,重写run()方法,在run()方法中写上子线程需要执行的任务就可以了。然后在测试的main()方法中new MyThread()。再调用start()方法。这样就完成了使用继承Thread,来实现子线程从创建到执行的整个过程。

2.实现Runnable接口

public class MyThreadRunnable implements Runnable {

    private String name;

    public MyThreadRunnable(String name){
this.name = name;
} @Override
public void run() {
System.out.println(name);
}
} public class MainTest { public static void main(String[] args){ MyThreadRunnable r1 = new MyThreadRunnable("r1");
MyThreadRunnable r2 = new MyThreadRunnable("r1");
MyThreadRunnable r3 = new MyThreadRunnable("r1"); Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3); t1.start();
t2.start();
t3.start();
}
}

MyThreadRunnable实现Runnable接口,并且在run()方法中实现自己的任务,这跟前面的很类似,只是后面要开启线程的时候不仅需要new MyThreadRunnable()而且还需要new Thread()并且把前面的对象传入,再通过Thread调用start()方法来启动线程。 
上面的方法来开启子线程,还可以用静态内部类来实现,这样代码看起来会更加简洁。

new Thread(new Runnable() {
@Override
public void run() {
System.out.println("xxxx");
}
}).start();

  

从代码层面来看,继承Thread看起来更加方便,但是java是单继承的,在实际生产中,一般都需要某个类,所以实现Runnable的用法会多一点。

使用Android特有的方法来实现异步

1.AsyncTask

public class MainActivity extends Activity {

    private ProgressBar mProgressBar;
private ImageView mImageView; @Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState); MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute("www.baidu.com/xxx.jpg");
} class MyAsyncTask extends AsyncTask<String, Integer, Bitmap>{ @Override
protected void onPreExecute() {
//这里是开始线程之前执行的,是在UI线程
mProgressBar.setMax();
super.onPreExecute();
} @Override
protected Bitmap doInBackground(String... params) {
//这是在后台子线程中执行的
Bitmap bitmap = null;
try {
URL url = new URL(params[]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream inputStream = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream);
publishProgress();//这里是更新进度
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
} @Override
protected void onCancelled() {
//当任务被取消时回调
super.onCancelled();
} @Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//更新进度
mProgressBar.setProgress(values[]);
} @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//当任务执行完成是调用,在UI线程
mImageView.setImageBitmap(bitmap);
}
} }

MyAsyncTask基础自AsyncTask,三个泛型分别为,String:是传入参数类型,可以传多个,Integer:是进度显示的参数类型,也可以传多个,Bitmap:是任务执行完的返回类型,这里就是返回一个Bitmap。 
使用AsyncTask来实现异步的有点就是简单便捷,各个过程都有明确的回调,过程可控。但是缺点就是要是执行多个异步,就会变得很复杂。

2.Handler

public class HandlerTestActivity extends Activity {

    Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.what;
if(what == ){
//在主线程中需要执行的操作,一般是UI操作
}
}
}; @Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState); Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//在子线程中执行任务,执行完成或需要通知UI线程时调用以下方法
mHandler.sendEmptyMessage();
}
});
thread.start();
}
}

上面就是最简单的使用Handler完成子线程和主线程的通信(子线程发消息给主线程)

public class LooperThreadActivity extends Activity {

    private Handler mHandler = null;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new MyThread().start();
//发消息到目标子线程
mHandler.obtainMessage().sendToTarget(); } class MyThread extends Thread{ @Override
public void run() {
super.run();
//1.建立消息循环,初始化Looper
Looper.prepare();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.what;
if(what == ){
//
}
}
};
//启动消息循环
Looper.loop();
}
}
}

上面是主线程发消息给子线程,也是比较类似的,只不过在子线程中,需要初始化Looper.prepare()和Looper.loop()。

RxJava

这个比较新,学习路线比较陡峭,但是一旦入门,使用起来真的很爽。

public class RxJavaTestActivity extends Activity {

    private ImageView mImageView;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); Observable.just("")
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String s) {
//可以在这里执行耗时操作,比如下载网络图片,然后转化为Bitmap
return null;
}
}).subscribeOn(Schedulers.io())//把工作线程指定为了IO线程
.observeOn(AndroidSchedulers.mainThread())//把回调线程指定为了UI线程
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
//这里是在UI线程,这里显示了图片
mImageView.setImageBitmap(bitmap);
}
});
}
}

这里是最简单的使用了RxJava,来实现异步操作。RxJava还有更多更强大的功能等你去发现。

Android实现异步的几种方法的更多相关文章

  1. Chrome模拟手机浏览器(iOS/Android)的三种方法,亲测无误!

    大网站都有推出自己的手机访问版本页面,不管是新闻类还是视频网站,我们在电脑是无法直接访问到手机网站的,比如我经常访问一个3g.qq.com这个手机站点,如果在电脑上直接打开它,则会跳转到其它页面,一般 ...

  2. 用Fiddler可以设置浏览器的UA 和 手动 --Chrome模拟手机浏览器(iOS/Android)的三种方法,亲测无误!

    附加以一种软件的方法是:用Fiddler可以设置浏览器的UA 以下3种方法是手动的 通过伪装User-Agent,将浏览器模拟成Android设备. 第一种方法:新建Chrome快捷方式 右击桌面上的 ...

  3. Android传递数据5种方法

       Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示 ...

  4. android 一题多改系列——android 打电话实现两种方法

    在android开发中,用户能够拨打电话是最基本的需求.俗话说“条条大路通罗马”,实现拨打电话的方式有多种,今天,就提供最常用两种. 首先,拨打电话,对于用户来说,是一个耗费的操作,因此,需要一定权限 ...

  5. android 图片叠加效果——两种方法

    效果图: 第一种: 第二种: 第一种是通过canvas画出来的效果: public void first(View v) { // 防止出现Immutable bitmap passed to Can ...

  6. android 图片叠加效果——两种方法的简介与内容 ,带解决Immutable bitmap passed to Canvas constructor错误

    第一种是通过canvas画出来的效果: public void first(View v) { // 防止出现Immutable bitmap passed to Canvas constructor ...

  7. android参数传递的几种方法

    Intent Intent i=new Intent(当前Activity.this,目标Activity.class); 1.传单值 传入: i. i.putExtra("名称" ...

  8. Android事件处理的三种方法

    一.基于监听 setOnClickListener,setOnLongClickListener.setOnTouchListener 注意:如果onTouchEvent方法return true,则 ...

  9. 【php】【异步】php实现异步的几种方法

    请参考  4种php常用的异步执行方式 ajax 和 img 的 src 属性 系统指令调用 (在php代码里面调用系统指令) curl socket通信 ​

随机推荐

  1. linux1--常用命令

    1.目录结构 2./etc:系统配置文件存放地 比如你的wsgi的配置文件,nginx 3./usr 应用程序存放地 比如你的jdk应用程序存放地 4./root 系统管理员root的家目录 4.1像 ...

  2. Spring Security获取已登录的用户信息的两种方法

    第一种是直接从session中手动拿: @RequestMapping(value = "/user", method = RequestMethod.GET)public Res ...

  3. SprimgMVC学习笔记(八)—— SpringMVC与前台json数据交互

    一.两种交互形式 可以看出,前台传过来的方式有两种,一种是传json格式的数据过来,另一种就是在url的末尾传普通的key/value串过来,针对这两种方式,在Controller类中会有不同的解析, ...

  4. Linux防火墙详解

    1.Linux防火墙基础 作为隔离内外网.过滤非法数据的有力屏障,防火墙通常按实现环境的不同分为硬件防火墙和软件防火墙.硬件防火墙是功能专一的硬件设备,具有比较全面的功能,其工作效率较高,但是加个昂贵 ...

  5. 项目中遇到的问题:前台 disabled 与 后台disabled

    TPRI项目流程,点[保存],“人员”服务器端控件,如果在前台disabled设置,则值会丢失:在后台设置disabled就可以.

  6. chafen

    //f(u)>=f(v)+w //求最大值 跑最短路 v->u -w //求最小值 跑最长路 u->v w

  7. eclipse.ini X64 Oxygen.2 Release (4.7.2) lombok

    X64 Eclipse Java EE IDE for Web Developers. Version: Oxygen.2 Release (4.7.2)Build id: 20171218-0600 ...

  8. Linux 网络配置及常用服务配置(Redhat 6)

    一.网络配置 1. VMWare 提供了三种网络工作模式供用户选择,他们分别是, ①Bridged(桥接模式): 如果网络中能提供多个IP地址,则使用桥接方式 ②NAT(网络地址转换模式): 如果网络 ...

  9. SqlServer自动备份作业

    /*********完整备份作业*********/ –完整备份,每周一次 USE Master GO declare @str varchar(100) set @str='D:\DBtext\jg ...

  10. oracle截取字符串,定索引

    转载:https://www.cnblogs.com/qmfsun/p/4493918.html 使用Oracle中Instr()和substr()函数: 1 2 3 4 5 6 7 8 9 10 1 ...