Android~AsyncTask异步操作DEMO学习解析
来源:互联网 发布:mac怎么安装mpv 编辑:程序博客网 时间:2024/05/21 14:04
大家好,今天我给大家介绍AsyncTask异步类的具体使用;AsyncTask是Android系统提供的轻量级的异步操作类,处理耗时操作任务在非UI线程中,提供回调接口,在回调接口中我们可以再UI线程中更新界面或执行UI线程中可操作的任务。
使用AsyncTask异步类我们先了解重写该类我们必须要重写该类的哪些方法?
doInBackground(Void... params);在非UI线程中执行处理耗时任务操作。
onPreExecute();异步类AsyncTask执行doInBackground方法之前,也就是在非UI线程执行之前,需要执行的方法。
onPostExecute(Void... params);异步类AsyncTask执行doInBackground方法之后,回调在UI线程中需要执行的方法。
onProgressUpdate(Void... params);异步类AsyncTask类在doInBackground方法执行过程中,需要更新UI线程中界面或者数据,我们需要调用publishProgress(Void... params)方法来执行可在UI线程中执行的此方法。
那么好了,现在我就用写一个DEMO,具体介绍该类的使用分析。
1)新建一个Android应用工程asynctask,应用结构如下:
2)我们在activity_home.xml设置一个Button按钮,作用就是进入进度条界面,具体代码如下:
3)我们在HomeActivity类中编写按钮的点击事件逻辑处理,具体代码如下:
package com.example.asynctask;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;public class HomeActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_home);}public void inprogress(View v){startActivity(new Intent(this, ProgressActivity.class));}}4)我们编写ProgressActivity.java类的代码,首先该类对应的布局文件是activity_progress.xml,布局文件中只是有一个ProgressBar控件,具体代码如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" > <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /></RelativeLayout>5)我们编写ProgressActivity.java类的代码,这里才是核心,具体代码如下:
package com.example.asynctask;import java.security.PublicKey;import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import android.view.View;import android.widget.ProgressBar;import android.widget.Toast;public class ProgressActivity extends Activity{private ProgressBar mProgressBar;private MyAsyncTask task;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_progress);mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);}@Overrideprotected void onResume() {super.onResume();task = new MyAsyncTask();task.execute();}class MyAsyncTask extends AsyncTask<Void, Integer, Void>{/** * 在执行耗时操作之前调用此方法 */@Overrideprotected void onPreExecute() {super.onPreExecute();mProgressBar.setVisibility(View.VISIBLE);Toast.makeText(ProgressActivity.this, "进度条开始", Toast.LENGTH_LONG).show();}/** * 在非UI线程中执行耗时操作 */@Overrideprotected Void doInBackground(Void... params) {for (int i = 0; i < 100; i++) {publishProgress(i);//更新UI线程进度条进度情况。try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}return null;}/** * 在执行耗时操作之后调用此方法 */@Overrideprotected void onPostExecute(Void result) {super.onPostExecute(result);mProgressBar.setVisibility(View.INVISIBLE);Toast.makeText(ProgressActivity.this, "进度条完毕", Toast.LENGTH_LONG).show();}/** * 在doInBackground非UI线程中执行耗时操作时候,调用publishProgress方法的时候才会调用该方法。 */@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);mProgressBar.setProgress(values[0]);}}}截止到此我们就可以算是告一段落了,那么我们开始用运行程序,程序运行非常完美!
但是当我们点击按钮进入,马上点击硬件返回,在点击按钮进入,马上点击硬件返回,在点击按钮进入,会发现等待比较长的时间进度条才开始显示运行,大家敲击代码到此运行一下,看看我说的情况是否存在呢!?
在我们异步类执行的过程,其实是放在一个异步池中了,它们是按照顺序执行的,如果其中一个没有执行完毕的话,那么我们后面的异步类只能等待!在我们点击硬件返回,在点击按钮的同时,新建了一个异步类将异步类放入异步池中,但是上一次的异步类还没有执行完毕呢,所以它只能等待!
好了,我们现在知道了原因,那么我们如何更正!?
我的解决方案就是将异步类的生命周期和Activity类的生命周期绑定在一起,那么我们可以再onPause方法中调用task.cancel(true);
那么现在我们在运行程序按照刚才的操作运行一下,结果发现和刚才情况一样没有变化!我们已经将task取消了啊!怎么会不起作用呢?
那么这个时候我们就要去查看task.cancel(true);源码去了:
/** * <p>Attempts to cancel execution of this task. This attempt will * fail if the task has already completed, already been cancelled, * or could not be cancelled for some other reason. If successful, * and this task has not started when <tt>cancel</tt> is called, * this task should never run. If the task has already started, * then the <tt>mayInterruptIfRunning</tt> parameter determines * whether the thread executing this task should be interrupted in * an attempt to stop the task.</p> * * <p>Calling this method will result in {@link #onCancelled(Object)} being * invoked on the UI thread after {@link #doInBackground(Object[])} * returns. Calling this method guarantees that {@link #onPostExecute(Object)} * is never invoked. After invoking this method, you should check the * value returned by {@link #isCancelled()} periodically from * {@link #doInBackground(Object[])} to finish the task as early as * possible.</p> * * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this * task should be interrupted; otherwise, in-progress tasks are allowed * to complete. * * @return <tt>false</tt> if the task could not be cancelled, * typically because it has already completed normally; * <tt>true</tt> otherwise * * @see #isCancelled() * @see #onCancelled(Object) */ public final boolean cancel(boolean mayInterruptIfRunning) { mCancelled.set(true); return mFuture.cancel(mayInterruptIfRunning); }在源码中我们可以看到在该方法中并没有将异步类取消掉,只是设置了一个标志位,在给出的注释中我们发现有一个isCancelled()的方法,我们在查看其源码:
/** * Returns <tt>true</tt> if this task was cancelled before it completed * normally. If you are calling {@link #cancel(boolean)} on the task, * the value returned by this method should be checked periodically from * {@link #doInBackground(Object[])} to end the task as soon as possible. * * @return <tt>true</tt> if task was cancelled before it completed * * @see #cancel(boolean) */ public final boolean isCancelled() { return mCancelled.get(); }从这源码中我们看到只是返回刚才我们设置的标志位而已。
那么我们就可以在后台doInBackground,onPostExecute执行开始过程中我们调用isCancelled()方法,则相关代码修改后如下:
/** * 在执行耗时操作之前调用此方法 */@Overrideprotected void onPreExecute() {super.onPreExecute();mProgressBar.setVisibility(View.VISIBLE);Toast.makeText(ProgressActivity.this, "进度条开始", Toast.LENGTH_LONG).show();}/** * 在非UI线程中执行耗时操作 */@Overrideprotected Void doInBackground(Void... params) {for (int i = 0; i < 100; i++) {if(isCancelled()){break;}publishProgress(i);//更新UI线程进度条进度情况。try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}return null;}/** * 在执行耗时操作之后调用此方法 */@Overrideprotected void onPostExecute(Void result) {super.onPostExecute(result);if(isCancelled()){return;}mProgressBar.setVisibility(View.INVISIBLE);Toast.makeText(ProgressActivity.this, "进度条完毕", Toast.LENGTH_LONG).show();}/** * 在doInBackground非UI线程中执行耗时操作时候,调用publishProgress方法的时候才会调用该方法。 */@Overrideprotected void onProgressUpdate(Integer... values) {if(isCancelled()){return;}super.onProgressUpdate(values);mProgressBar.setProgress(values[0]);}现在我们运行的话,就应该不会出现任何的问题了。
好了就写到这里吧!有问题的话大家可以一起探讨啊! 谢谢!
- Android~AsyncTask异步操作DEMO学习解析
- Android AsyncTask 异步操作Demo
- Android异步操作AsyncTask学习
- Android 学习1: AsyncTask异步操作
- Android学习之Asynctask异步操作
- Android AsyncTask Demo异步下载
- Android异步操作AsyncTask
- Android AsyncTask异步操作
- Android 异步操作AsyncTask
- Android 异步操作AsyncTask
- Android异步操作 AsyncTask
- Android 异步操作AsyncTask
- Android 异步操作AsyncTask
- Android AsyncTask异步操作
- android - AsyncTask 异步操作
- Android 异步操作AsyncTask
- Android异步操作AsyncTask
- Hello Android - AsyncTask异步操作
- (java)leetcode 3sum cloest
- 减治法之插入排序(C实现)
- hadoop入门例子(一)-输出hdfs上面的某一个目录下面的文件
- OC中有关JS的相关操作
- (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
- Android~AsyncTask异步操作DEMO学习解析
- unity3d 抛物线
- Android M新控件之FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用
- C/S通信---服务器IO多路复用模型之epoll的使用
- Android Stuido超全快捷键
- Android控件之跑马灯效果的TextView
- autocomplete
- 临时解决mysql 8小时失效的方法
- MATLAB中如何输入希腊字母