Thread Handler 通过使用 Service和 IntentService解决ANR

Thread

三种方式

连接服务器的功能,是属于耗时任务,所以必须放在子线程

如果子线程已经执行了耗时操作,那么就不能修改视图的属性了;视图的属性只能在UI线程去修改

方法1(继承Thread)

class MyThread extends Thread{
      @Override
            public void run() {
                super.run();
          try {
              sleep(3000);
              Log.i("123", "123");
          } catch (InterruptedException e) {
              e.printStackTrace();
         }
 	  }
}

MyThread myThead = new MyThread();
myThread.start();

方法2(实现Runnable接口)

class MyRunnable implements Runnable {
	@Override
	public void run() {
		try {
			Thread.sleep(3000);

			String result = "runnable 345345";
			Log.i("runnable", result);

		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();

方法三(匿名 Runnable)

new Thread(new Runnable() {
	@Override
    public void run() {
    	// 耗时任务
		try {
			Thread.sleep(3000);
			String result = "匿名线程";
			Log.i("匿名线程",result);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}).start();

Handler

定义

子线程中是没有办法修改页面,这个时候需瑶借助Handler给主线程传递消息

主线程接收到Hander消息后,开始执行修改UI

案例

public class MainActivity2 extends AppCompatActivity {
    // 声明容器
    private TextView tv1;

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

        // 根据ID获取页面控件
        tv1 = findViewById(R.id.tv1);
		new Thread(new Runnable() {
            @Override
            public void run()
    			//模拟一个链接服务器的耗时操作
                try {
                    Thread.sleep(300);
                    
                    String name = "炸炸";
                    Message message = new Message();
                    message.what = 1;
                    message.obj = name;
                    handler.handleMessage(message);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();
	}
    Handler handler = new Handler(Looper.getMainLooper()) {
     @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            //判断子线程传输的线程
            if (msg.what == 1) {
                //修改UI线程(进行页面修改)
                String result = (String) msg.obj;
                tv1.setText(result);
            }
       	}
	};
}

进度条案例

public class MainActivity3 extends AppCompatActivity {
	//设置容器
    private ProgressBar progressBar;
    int status = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        //根据ID获取页面控件
        progressBar = findViewById(R.id.progressBar);
		//(匿名 Runnable)使用
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 循环对status进行值得修改
                while (status != 100) {
                    try {
                        Thread.sleep(100);
                        status++;
                        handler.sendEmptyMessage(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }).start();
    }

    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what ==2) {
                progressBar.setProgress(status);
            }
        }
    };
}

通过使用Service和 IntentService解决ANR

Service和IntentService的区别

IntentService
IntentService是Service的子类,比普通的Service增加了额外的功能。先看Service本身存在两个问题:

Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中;
Service也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务;
IntentService特征:

会创建独立的worker线程来处理所有的Intent请求;
会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;
为Service的onBind()提供默认实现,返回null;
为Service的onStartCommand提供默认实现,将请求Intent添加到队列
会自动开启线程,也不会自动停止线程所以需要我们手动创建和关闭

怎么创建IntentService

1.新建一个Class文件

2.继承IntentService

​ 3.实现onHandleIntent 和 构造方法

  1. 在AndroidManifest.xml中注册,注册时发现报错,报错的原因是没有无参的构造方法,解决办法:创建无参的构造方法

也可以通过下面的步骤新建
在这里插入图片描述

但是需要删除一些没用的内容 跟 手动创建一样也需要自己手动再添加一个无参的构造方法
System.currentTimeMillis() 	//获取当前系统时间

案例

//使用Service
		button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            //跳转到Service
                Intent intent = new Intent(MainActivity.this,MyService.class);
                startService(intent);
            }
        });
        
        
        
//使用IntentService      
        
        bt_intentService =findViewById(R.id.bt_intentService);
        bt_intentService.setOnClickListener(new View.OnClickListener() {
        //跳转到IntentService 
            @Override
            public void onClick(View view) {
                Intent intent =new Intent(MainActivity.this,MyIntentService.class);
                startService(intent);
            }
        });

Service

package com.example.myapplicationsirwz;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {
    public MyService() {
    }


    @Override
    public void onCreate() {
        Log.i("Service","Service创建");

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Service","Service已开启");
        new Thread(new Runnable() {
            @Override
            public void run() {
            //获取当前系统时间加上20秒
                long sum = System.currentTimeMillis() + 20*1000;
                //判断当前系统时间小于定义时间就进行延时操作
                while (System.currentTimeMillis() < sum){
                    synchronized (this){
                        try {
                            wait(sum-System.currentTimeMillis());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                stopSelf();
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("Service","Service被销毁");
        super.onDestroy();
    }


    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }


}

IntentService

package com.example.myapplicationsirwz;

import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
import android.util.Log;

import androidx.annotation.Nullable;


public class MyIntentService extends IntentService {

    /**
     * @param name
     * @deprecated
     */
     //有参构造方法
    public MyIntentService(String name) {
        super(name);
    }
    //无参构造
    public MyIntentService() {
        super("MyIntentService");
    }
    //模拟进行延时操作
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        Log.i("IntentService","IntentService已开启");
                long sum = System.currentTimeMillis() + 20*1000;
                while (System.currentTimeMillis() < sum) {
                    synchronized (this) {
                        try {
                            wait(sum - System.currentTimeMillis());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
        return super.onStartCommand(intent, flags, startId);
    }
    
    //在 onDestroy 查看IntentService的线程是否存在
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("IntentService","已被销毁");
    }


    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

    }
}

总结

在Activity进行 耗时操作

需要使用 Thread 构建子线程 子线程不能修改UI线程

这个同时需要借助 handler 来修改UI页面内容

通过使用Service IntentService来进行处理延时操作的话

Service Service不会自动开启线程,也不会自动停止线程

IntentService 自动开启线程,并在执行完毕后,关闭线程
super.onDestroy();
Log.i(“IntentService”,“已被销毁”);
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {

}

}


## 总结

在Activity进行 耗时操作

需要使用 Thread 构建子线程 子线程不能修改UI线程

这个同时需要借助 handler 来修改UI页面内容

通过使用Service IntentService来进行处理延时操作的话

Service  Service不会自动开启线程,也不会自动停止线程

IntentService	自动开启线程,并在执行完毕后,关闭线程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值