相信大家学习了异步Async,也使用之进行了网络下载,这里使用async进行倒计时操作:
(一)复习一下Async:
异步任务:
什么是异步任务?一切使用多线程来完成的任务均可以称为异步任务----------->使用线程来完成的任务
使用异步任务有啥好处呢:提高CPU的利用率
使用异步任务坏处在哪里呢?
1>:加重了CPU的负担
2>:容易出现线程安全问题
3>:容易造成死锁
使用异步任务的必要性
Android中单线程模型
Anroid到底是如何来运行程序的?
当Android的虚拟机在调用咋们的Activiyt对象来完成现实压栈的时候
将当前的对象运行在了一个叫做MainThread的主线程中,这个线程又叫做UI线程
UI线程这个名字是如何得来的呢?是因为这个主线程我那个只有一个特定的工作那就是刷新UI 这个线程的主要工作就是管理UI
Android的单线程模型指的是什么?
指的就是上面我们提到的这个UI线程
那么这个模型具体指的是什么呢?
1>:在Android的单线程模型中第一点:刷新UI只能在主线程来完成
2>:耗时操作必须在异步中完成有哪些是耗时的 操作? 网络我访问 IO流的使用 数据库的访问 咋们以后遇到这个问题的时候需要使用线程来完成
所以:
需要的做多的使用异步来完成的是:
网络访问:软件------>服务器数据的获取,开发的话那么访问网和数据库都要放到一异步任务重去完成
数据库的访问:
2.3以前的版本 山寨市场上不规整 有些手机 三星必须要求访问数据库必须放子线程 中兴 华为 联想 只要是数据库的访问都放到线程中
(二)异步任务的用法
AsyncTask是什么?是一个线程池
对于Android系统而言4.4以前的版本
允许一次性最多运行5个线程
内部定义了最多在线程池中存在的线程数是128
对于4.4以后的版本
1>:那个线程最最多运行的线程数也是根据当前CPU的性能来动态决定的2-4个线程,所以一般就拿来做些比较小的异步操作
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
2>:当前线程池中的最大的线程数也是动态决定的
注意:在4.4的版本以后那个线程池的默认的是同一时间段只能执行一个任务
但是我们也可以自定义线程池,这个后边说到。
(三)异步任务的取消(后边会用到)
myAsyncTask.cancel(true) 这个方法和线程中的interrupt方法是一样的能够终止正处于阻塞状态的线程。
很多开发者会认为一个在Activity中创建的AsyncTask会随着Activity的销毁而销毁。然而事实并非如此。AsyncTask会一直执行, 直到doInBackground()方法执行完毕。然后,如果 cancel(boolean)被调用, cancel(true)调用的是onCancelled(Result result) 方法那么onCancelled(Result result) 方法会被执行;否则,执onPostExecute(Result result) 方法。如果我们的Activity销毁之前,没有取消 AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。因为它想要处理的view已经不存在了。所以,我们总是必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确地取消。
另外,即使我们正确地调用了cancle() 也未必能真正地取消任务。因为如果在doInBackgroud里有一个不可中断的操作,比如BitmapFactory.decodeStream(),那么这个操作会继续下去。就是在图片的操作一旦进行是取消不了的!!
myAsyncTask.cancel(true) 这个方法和线程中的interrupt方法是一样的能够终止正处于阻塞状态的线程。
很多开发者会认为一个在Activity中创建的AsyncTask会随着Activity的销毁而销毁。然而事实并非如此。AsyncTask会一直执行, 直到doInBackground()方法执行完毕。然后,如果 cancel(boolean)被调用, cancel(true)调用的是onCancelled(Result result) 方法那么onCancelled(Result result) 方法会被执行;否则,执onPostExecute(Result result) 方法。如果我们的Activity销毁之前,没有取消 AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。因为它想要处理的view已经不存在了。所以,我们总是必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确地取消。
另外,即使我们正确地调用了cancle() 也未必能真正地取消任务。因为如果在doInBackgroud里有一个不可中断的操作,比如BitmapFactory.decodeStream(),那么这个操作会继续下去。就是在图片的操作一旦进行是取消不了的!!
好的,上代码:
public class GuideActivity extends AppCompatActivity { @Bind(R.id.skip_text) TextView skipText; @Bind(R.id.skip_seconds) TextView skipSeconds; private TimeCount time; private int count = 10; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_guide); ButterKnife.bind(this);
//异步类count: final Count myCount = new Count(this); myCount.execute(count); skipText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(GuideActivity.this, HomePageActivity.class); startActivity(intent); finish();
//如果中途点击跳过浏览,那么就调用取消这个方法 myCount.cancel(true); } });好的,下面是count代码:
package com.example.administrator.newsinfor.utils; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.os.AsyncTask; import android.widget.TextView; import android.widget.Toast; import com.example.administrator.newsinfor.Activity.GuideActivity; import com.example.administrator.newsinfor.Activity.HomePageActivity; import com.example.administrator.newsinfor.R; /** * Created by Administrator on 2016/10/20 0020. */ public class Count extends AsyncTask<Integer, Integer, Integer> { // 参数Context context;第一个参数含义接受传过来的前面execute的参数就是doinbackgroud返回参数。 // 参数2:进度更新upgrade,参数3:返回值doin的返回类型post的传入参数 //你写这边的构造函数参数,需要自己这边有定义才行 private GuideActivity guideActivity;//这个有实际意义,不是空的对象需要赋值 private int num; private TextView skip_seconds; public Count(Context context) { if (context instanceof GuideActivity) { guideActivity = (GuideActivity) context; } } @Override protected void onPreExecute() { super.onPreExecute(); skip_seconds = (TextView) guideActivity.findViewById(R.id.skip_seconds); } @Override protected Integer doInBackground(Integer... params) { int count = params[0]; while (count > 0) { publishProgress(count); count--; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); skip_seconds.setClickable(false); skip_seconds.setText(values[0] + "秒"); skip_seconds.setTextColor(Color.RED); } @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); //运行到这里表示运行完了,来个事后提示,我调用了oncacell来取消这步操作 Toast.makeText(guideActivity, "进入主页面", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(guideActivity, HomePageActivity.class); guideActivity.startActivity(intent); guideActivity.finish(); } }
当然也可以使用安卓自带的类来实现:
/* 定义一个倒计时的内部类 */ class TimeCount extends CountDownTimer { public TimeCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval);//参数依次为总时长,和计时的时间间隔 } @Override public void onFinish() {//计时完毕时触发 Intent intent = new Intent(GuideActivity.this, HomePageActivity.class); startActivity(intent); finish(); } @Override public void onTick(long millisUntilFinished) {//计时过程显示 skipSeconds.setClickable(false); skipSeconds.setText(millisUntilFinished / 1000 + "秒"); skipSeconds.setTextColor(Color.RED); } }
ok,that is all~