progressBar.setProgress(0);
execute.setEnabled(true);
cancel.setEnabled(false);
}
}
}
布局文件main.xml代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:orientation=“vertical”
android:layout_width=“fill_parent”
android:layout_height=“fill_parent”>
<Button
android:id=“@+id/execute”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”
android:text=“execute”/>
<Button
android:id=“@+id/cancel”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”
android:enabled=“false”
android:text=“cancel”/>
<ProgressBar
android:id=“@+id/progress_bar”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”
android:progress=“0”
android:max=“100”
style=“?android:attr/progressBarStyleHorizontal”/>
<ScrollView
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”>
<TextView
android:id=“@+id/text_view”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”/>
因为需要访问网络,所以我们还需要在AndroidManifest.xml中加入访问网络的权限:
二、 AsyncTask的实现基本原理
===================
上面介绍了AsyncTask的基本应用,有些朋友也许会有疑惑,AsyncTask内部是怎么执行的呢,它执行的过程跟我们使用Handler又有什么区别呢?答案是:AsyncTask是对Thread+Handler良好的封装,在android.os.AsyncTask代码里仍然可以看到Thread和Handler的踪迹。下面就向大家详细介绍一下AsyncTask的执行原理。
源代码如下 :
/**
-
Override this method to perform a computation on a background thread. The
-
specified parameters are the parameters passed to {@link #execute}
-
by the caller of this task.
-
This method can call {@link #publishProgress} to publish updates
-
on the UI thread.
-
@param params The parameters of the task.
-
@return A result, defined by the subclass of this task.
-
这是一个abstract 方法,因此必须覆写。
-
@see #onPreExecute()
-
@see #onPostExecute
-
@see #publishProgress
*/
protected abstract Result doInBackground(Params… params);
/**
-
Runs on the UI thread before {@link #doInBackground}.
-
@see #onPostExecute
-
@see #doInBackground
*/
protected void onPreExecute() {
}
/**
-
Runs on the UI thread after {@link #doInBackground}. The
-
specified result is the value returned by {@link #doInBackground}
-
or null if the task was cancelled or an exception occured.
*后台操作执行完后会调用的方法,在此更新UI。
-
@param result The result of the operation computed by {@link #doInBackground}.
-
@see #onPreExecute
-
@see #doInBackground
*/
@SuppressWarnings({“UnusedDeclaration”})
protected void onPostExecute(Result result) {
}
/**
-
Runs on the UI thread after {@link #publishProgress} is invoked.
-
The specified values are the values passed to {@link #publishProgress}.
-
@param values The values indicating progress.
-
传值更新进度条
-
@see #publishProgress
-
@see #doInBackground
*/
@SuppressWarnings({“UnusedDeclaration”})
protected void onProgressUpdate(Progress… values) {
}
/**
-
Executes the task with the specified parameters. The task returns
-
itself (this) so that the caller can keep a reference to it.
-
This method must be invoked on the UI thread. 注意execute方法必须在UI线程中调用
-
@param params The parameters of the task.
-
@return This instance of AsyncTask.
-
@throws IllegalStateException If {@link #getStatus()} returns either
-
{@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*/
public final AsyncTask<Params, Progress, Result> execute(Params… params) {
if (mStatus != Status.PENDING) {
// 状态检测,只有在PENDING状态下才能正常运行,构造抛出异常
switch (mStatus) {
case RUNNING:
throw new IllegalStateException(“Cannot execute task:”
- " the task is already running.");
case FINISHED:
throw new IllegalStateException(“Cannot execute task:”
-
" the task has already been executed "
-
“(a task can be executed only once)”);
}
}
mStatus = Status.RUNNING;
// 正在执行任务前的准备处理
onPreExecute();
// 获得从UI现存传递来的参数
mWorker.mParams = params;
// 交给线程池管理器进行调度,参数为FutureTask类型,构造mFuture时mWorker被传递了进去,后边会继续分析
sExecutor.execute(mFuture);
// 返回自身,使得调用者可以保持一个引用
return this;
}
/**
-
This method can be invoked from {@link #doInBackground} to
-
publish updates on the UI thread while the background computation is
-
still running. Each call to this method will trigger the execution of
-
{@link #onProgressUpdate} on the UI thread.
-
@param values The progress values to update the UI with.
-
@see #onProgressUpdate
-
@see #doInBackground
*/
protected final void publishProgress(Progress… values) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult(this, values)).sendToTarget();
}
我们可以看到关键几个步骤的方法都在其中。
1、 doInBackground(Params… params) 是一个抽象方法,我们继承AsyncTask时必须覆写此方法;
2、 onPreExecute()、onProgressUpdate(Progress… values)、onPostExecute(Result result)、onCancelled() 这几个方法体都是空的,我们需要的时候可以选择性的覆写它们;
3、 publishProgress(Progress… values) 是final修饰的,不能覆写,只能去调用,我们一般会在doInBackground(Params… params)中调用此方法来更新进度条;
**4、**另外,我们可以看到有一个Status的枚举类和getStatus()方法,Status枚举类代码段如下:
//初始状态
private volatile Status mStatus = Status.PENDING;
public enum Status {
/**
- Indicates that the task has not been executed yet.
*/
PENDING,
/**
- Indicates that the task is running.
*/
RUNNING,
/**
- Indicates that {@link AsyncTask#onPostExecute} has finished.
*/
FINISHED,
}
/**
-
Returns the current status of this task.
-
@return The current status.
*/
public final Status getStatus() {
return mStatus;
}
可以看到,AsyncTask的初始状态为 PENDING ,代表待定状态, RUNNING 代表执行状态, FINISHED 代表结束状态,这几种状态在AsyncTask一次生命周期内的很多地方被使用,非常重要。
在execute函数中涉及到三个陌生的变量:mWorker、sExecutor、mFuture,我们也会看一下:
关于sExecutor,它是java.util.concurrent.ThreadPoolExecutor的实例,用于管理线程的执行。代码如下:
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 10;
//新建一个队列用来存放线程
private static final BlockingQueue sWorkQueue =
new LinkedBlockingQueue(10);
//新建一个线程工厂
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
//新建一个线程
public Thread newThread(Runnable r) {
return new Thread(r, “AsyncTask #” + mCount.getAndIncrement());
}
};
//新建一个线程池执行器,用于管理线程的执行
private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
mWorker实际上是AsyncTask的一个的抽象内部类的实现对象实例,它实现了Callable接口中的call()方法,代码如下:
[java] view plaincopy
private static abstract class WorkerRunnable<Params, Result> implements Callable {
Params[] mParams;
}
而mFuture实际上是 java.util.concurrent.FutureTask 的实例,下面是它的FutureTask类的相关信息:
/**
-
A cancellable asynchronous computation.
-
…
*/
public class FutureTask implements RunnableFuture {
public interface RunnableFuture extends Runnable, Future {
/**
-
Sets this Future to the result of its computation
-
unless it has been cancelled.
*/
void run();
}
可以看到FutureTask是一个可以中途取消的用于异步计算的类。
下面是mWorker和mFuture实例在AsyncTask中的体现:
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask mFuture;
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
//call方法被调用后,将设置优先级为后台级别, 然后调用AsyncTask的doInBackground方法
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);
}
};
// 在mFuture实例中,将会调用mWorker做后台任务,完成后会调用done方法。
// 这里将mWorker作为参数传递给了mFuture对象
mFuture = new FutureTask(mWorker) {
@Override
protected void done() {
Message message;
Result result = null;
try {
result = get();
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException(“An error occured while executing doInBackground()”,
e.getCause());
} catch (CancellationException e) {
//发送取消任务的消息
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult(AsyncTask.this, (Result[]) null));
message.sendToTarget();
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
- “doInBackground()”, t);
}
//发送显示结果的消息
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(AsyncTask.this, result));
message.sendToTarget();
}
};
}
我们看到上面的代码中,mFuture实例对象的done()方法中,如果捕捉到了CancellationException类型的异常,则发送一条“MESSAGE_POST_CANCEL”的消息;如果顺利执行,则发送一条“MESSAGE_POST_RESULT”的消息,而消息都与一个sHandler对象关联。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
写在最后
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从哪里入手去学习,对此我整理了一些资料
如果你熟练掌握以下列出的知识点,相信将会大大增加你通过前两轮技术面试的几率!这些内容都供大家参考,互相学习。
①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包,最后觉得有帮助、有需要的朋友可以点个赞
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
没有方向感,不知道该从哪里入手去学习,对此我整理了一些资料**
如果你熟练掌握以下列出的知识点,相信将会大大增加你通过前两轮技术面试的几率!这些内容都供大家参考,互相学习。
①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包,最后觉得有帮助、有需要的朋友可以点个赞
[外链图片转存中…(img-xY4aNIsa-1712584305298)]
[外链图片转存中…(img-DESVrzve-1712584305299)]
[外链图片转存中…(img-7bv9Zoyg-1712584305299)]
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算