Android的UI线程主要负责处理用户的按键事件、触屏事件等。因此其他阻塞UI线程的操作不应该在主线程中操作。为了避免UI线程失去响应的问题,Android程序采用将耗时操作放在新线程中完成的方式,但是新线程可能需要动态更新UI组件,比如获取网络资源操作放在新线程中完成。但由于新线程不允许直接更新山I组件,为了解决这个问题,Android提供了异步任务 (AsyncTask) 的方式实现异步线程的操作。
运行环境
- Windows 10
- Android Studio Arctic Fox (2020.3.1)
- jdk1.7.0_67
本次实验我们使用该方法从网络上下载一张图片
AsyncTask
AsyncTask<Params,Progress,Result>
是一个抽象类,通常被用于继承,继承时要指定如下三个泛型参数
①Params
启动任务执行时的输入参数的类型。
ImageDownTask task=new ImageDownTask(img);
task.execute(url);
②Progress
后台任务完成的进度值的类型。
protected void onProgressUpdate(Void... values)
③Result
后台任务完成后返回结果的类型。
protected Bitmap doInBackground(String... strings)
使用方法
(1)创建AsyncTask的子类,并指定参数类型。如果某个参数不需要,则指定为Void类型,
(2)实现AsyncTask的方法,如doTnBackground (Params•••):后台线程将要完成的功能,一般有获取网络资源等耗时性的操作;第二个方法onPostExecute (Result result):在do InBackground ( 方法执行完以后,系统会自动调用onPostExecute 0方法,并接受其返回值。这里一般负责更新UI线程等操作。
(3)调用AsyncTask子类的实例的execute (Params•• params)方法执行耗时操作
新建一个项目
1.添加控件
在activity_main.xml中添加一个ImageView和一个Button控件(我采用的是线性布局)。
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="195dp" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载" />
2.声明控件并对Button设置监听
在MainActivity中对刚添加的两个控件声明,并对Button设置监听。
创建一个异步任务类
@Override
public void onClick(View view) {
ImageDownTask task=new ImageDownTask(img);
task.execute(url);
}
声明一个url,该url名称必须与task.execute(url);
中url名称相同。
private String url="图片链接";
完整代码:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private ImageView img;
private Button btn;
private String url="http://pic1.win4000.com/mobile/2018-11-05/5bdfd9407a9b2.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
img=(ImageView)findViewById(R.id.img);
btn=(Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ImageDownTask task=new ImageDownTask(img);
task.execute(url);
}
});
}
}
3.继承AsyncTask
新建一个Java Class,命名为ImageDownTask.java
继承AsyncTask
public class ImageDownTask extends AsyncTask<String,Void, Bitmap>
4.定义下载图片功能(后台处理逻辑)
在ImageDownTask.java中添加以下代码URL url=new URL(strings[0]);
是因为只传递了一个参数,URL是一个数组,所以这里写0。
//后台处理逻辑(下载图片的功能在此方法中实现)
@Override
protected Bitmap doInBackground(String... strings) {
//形参接受输入的参数(下载图片的地址)
Bitmap bmp=null;
try {
URL url=new URL(strings[0]);
//通过URL是客户端与服务器端建立连接
HttpURLConnection coon=(HttpURLConnection) url.openConnection();
//I/O流
InputStream is=coon.getInputStream();
//缓冲流
BufferedInputStream bis=new BufferedInputStream(is);
//将缓冲流中数据封装成图片
bmp = BitmapFactory.decodeStream(bis);
//下载完成后,关闭I/O管道
bis.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bmp;
}
对img进行初始化,否则在MainActivity中ImageDownTask task=new ImageDownTask(img);
会获取为空,这里直接通过构造方法进行初始化。
private ImageView img;
public ImageDownTask(ImageView img) {
//通过构造方法进行依赖注入
this.img = img;
}
当图片下载完成后需要更新,显示出图片
//更新
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
img.setImageBitmap(bitmap);
}
}
5.开启联网权限
写完上面的代码后,还需要开启模拟器的联网权限。
在项目目录中点击manifests,选择AndroidManifest.xml,在<application ··· </application>
标签后添加如下代码
<uses-permission android:name="android.permission.INTERNET"/>
在<application ··· </application>
标签内添加如下代码
android:usesCleartextTraffic="true"
牛!好厉害
非常好
111,学习一下
很有帮助
很有帮助
学习一下
厉害666
啦啦啦啦啦啦