2024年Android最新并发编程之Android中AsyncTask使用详解(四)(2),美团三面结束后多久有消息

作者2013年从java开发,转做Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

参与过不少面试,也当面试官 面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我整理了一份阿里P7级别的最系统的Android开发主流技术,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你想深入系统学习Android开发,成为一名合格的高级工程师,可以收藏一下这些Android进阶技术选型

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

高级UI与自定义view;
自定义view,Android开发的基本功。

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

NDK开发;
未来的方向,高薪必会。

前沿技术;
组件化,热升级,热修复,框架设计

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • Params表示用于AsyncTask执行任务的参数的类型

  • Progress表示在后台线程处理的过程中,可以阶段性地发布结果的数据类型

  • Result表示任务全部完成后所返回的数据类型
    我们通过调用AsyncTask的execute()方法传入参数并执行任务,然后AsyncTask会依次调用以下四个方法:

  • onPreExecute
    该方法的签名如下所示:

该方法有MainThread注解,表示该方法是运行在主线程中的。在AsyncTask执行了execute()方法后就会在UI线程上执行onPreExecute()方法,该方法在task真正执行前运行,我们通常可以在该方法中显示一个进度条,从而告知用户后台任务即将开始。

  • doInBackground
    该方法的签名如下所示:

该方法有WorkerThread注解,表示该方法是运行在单独的工作线程中的,而不是运行在主线程中。doInBackground会在onPreExecute()方法执行完成后立即执行,该方法用于在工作线程中执行耗时任务,我们可以在该方法中编写我们需要在后台线程中运行的逻辑代码,由于是运行在工作线程中,所以该方法不会阻塞UI线程。该方法接收Params泛型参数,参数params是Params类型的不定长数组,该方法的返回值是Result泛型,由于doInBackgroud是抽象方法,我们在使用AsyncTask时必须重写该方法。在doInBackground中执行的任务可能要分解为好多步骤,每完成一步我们就可以通过调用AsyncTask的publishProgress(Progress…)将阶段性的处理结果发布出去,阶段性处理结果是Progress泛型类型。当调用了publishProgress方法后,处理结果会被传递到UI线程中,并在UI线程中回调onProgressUpdate方法,下面会详细介绍。根据我们的具体需要,我们可以在doInBackground中不调用publishProgress方法,当然也可以在该方法中多次调用publishProgress方法。doInBackgroud方法的返回值表示后台线程完成任务之后的结果。

  • onProgressUpdate
    上面我们知道,当我们在doInBackground中调用publishProgress(Progress…)方法后,就会在UI线程上回调onProgressUpdate方法,该方法的方法签名如下所示:

该方法也具有MainThread注解,表示该方法是在主线程上被调用的,且传入的参数是Progress泛型定义的不定长数组。如果在doInBackground中多次调用了publishProgress方法,那么主线程就会多次回调onProgressUpdate方法。

  • onPostExecute
    该方法的签名如下所示:

该方法也具有MainThread注解,表示该方法是在主线程中被调用的。当doInBackgroud方法执行完毕后,就表示任务完成了,doInBackgroud方法的返回值就会作为参数在主线程中传入到onPostExecute方法中,这样就可以在主线程中根据任务的执行结果更新UI。

下面我们就以下载多个文件的示例演示AsyncTask的使用过程。

布局文件如下所示:

界面上有一个“开始下载”的按钮,点击该按钮即可通过AsyncTask下载多个文件,对应的Java代码如下所示:

package com.ispring.asynctask;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class MainActivity extends Activity implements Button.OnClickListener {

TextView textView = null;
Button btnDownload = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textView);
btnDownload = (Button)findViewById(R.id.btnDownload);
Log.i(“iSpring”, "MainActivity -> onCreate, Thread name: " + Thread.currentThread().getName());
}

@Override
public void onClick(View v) {
//要下载的文件地址
String[] urls = {
“http://blog.csdn.net/iispring/article/details/47115879”,
“http://blog.csdn.net/iispring/article/details/47180325”,
“http://blog.csdn.net/iispring/article/details/47300819”,
“http://blog.csdn.net/iispring/article/details/47320407”,
“http://blog.csdn.net/iispring/article/details/47622705”
};

DownloadTask downloadTask = new DownloadTask();
downloadTask.execute(urls);
}

//public abstract class AsyncTask<Params, Progress, Result>
//在此例中,Params泛型是String类型,Progress泛型是Object类型,Result泛型是Long类型
private class DownloadTask extends AsyncTask<String, Object, Long> {
@Override
protected void onPreExecute() {
Log.i(“iSpring”, "DownloadTask -> onPreExecute, Thread name: " + Thread.currentThread().getName());
super.onPreExecute();
btnDownload.setEnabled(false);
textView.setText(“开始下载…”);
}

@Override
protected Long doInBackground(String… params) {
Log.i(“iSpring”, "DownloadTask -> doInBackground, Thread name: " + Thread.currentThread().getName());
//totalByte表示所有下载的文件的总字节数
long totalByte = 0;
//params是一个String数组
for(String url: params){
//遍历Url数组,依次下载对应的文件
Object[] result = downloadSingleFile(url);
int byteCount = (int)result[0];
totalByte += byteCount;
//在下载完一个文件之后,我们就把阶段性的处理结果发布出去
publishProgress(result);
//如果AsyncTask被调用了cancel()方法,那么任务取消,跳出for循环
if(isCancelled()){
break;
}
}
//将总共下载的字节数作为结果返回
return totalByte;
}

//下载文件后返回一个Object数组:下载文件的字节数以及下载的博客的名字
private Object[] downloadSingleFile(String str){
Object[] result = new Object[2];
int byteCount = 0;
String blogName = “”;
HttpURLConnection conn = null;
try{
URL url = new URL(str);
conn = (HttpURLConnection)url.openConnection();
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int length = -1;
while ((length = is.read(buf)) != -1) {
baos.write(buf, 0, length);
byteCount += length;
}
String respone = new String(baos.toByteArray(), “utf-8”);
int startIndex = respone.indexOf(“”);<br/> if(startIndex > 0){<br/> startIndex += 7;<br/> int endIndex = respone.indexOf(“”);
if(endIndex > startIndex){
//解析出博客中的标题
blogName = respone.substring(startIndex, endIndex);
}
}
}catch(MalformedURLException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally {
if(conn != null){
conn.disconnect();
}
}
result[0] = byteCount;
result[1] = blogName;
return result;
}

@Override
protected void onProgressUpdate(Object… values) {
Log.i(“iSpring”, "DownloadTask -> onProgressUpdate, Thread name: " + Thread.currentThread().getName());
super.onProgressUpdate(values);
int byteCount = (int)values[0];
String blogName = (String)values[1];
String text = textView.getText().toString();
text += “\n博客《” + blogName + “》下载完成,共” + byteCount + “字节”;
textView.setText(text);
}

@Override
protected void onPostExecute(Long aLong) {
Log.i(“iSpring”, "DownloadTask -> onPostExecute, Thread name: " + Thread.currentThread().getName());
super.onPostExecute(aLong);
String text = textView.getText().toString();
text += “\n全部下载完成,总共下载了” + aLong + “个字节”;
textView.setText(text);
btnDownload.setEnabled(true);
}

@Override
protected void onCancelled() {
Log.i(“iSpring”, "DownloadTask -> onCancelled, Thread name: " + Thread.currentThread().getName());

总结

这次面试问的还是还是有难度的,要求当场写代码并且运行,也是很考察面试者写代码
因为Android知识体系比较庞大和复杂的,涉及到计算机知识领域的方方面面。在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

面试题集合/面经、及系列技术文章等,资源持续更新中…**

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值