运行效果
实现步骤
- 新建一个布局文件,在布局中添加相应控件并设置参数
- 设置网络请求权限
- 新建一个类GetPicThread实现Runnable接口
- 定义一个handler用于将数据传送到主线程中
- 使用建造者模式完成属性赋值
- 在run()方法中完成网络图片的获取
- 在MainActivity中完成图片显示
图片的链接:
https://img2.mukewang.com/5adfee7f0001cbb906000338-240-135.jpg
创建GetPicThread类
这个类实现了Runnable接口,在本类的run()
方法中将通过传入的path
和handler
对象来完成网络图片的获取
使用建造者模式可以简化类的实例化代码。这个类的私有属性只有两个,建造者模式的优点并没有体现得很明显
public class GetPicThread implements Runnable{
private String path;
private Handler handler;
private GetPicThread(Builder builder) {
this.path = builder.path;
this.handler = builder.handler;
}
// 建造者模式
public static class Builder{
private String path;
private Handler handler;
public Builder setPath(String path) {
this.path = path;
return this;
}
public Builder setHandler(Handler handler) {
this.handler = handler;
return this;
}
public GetPicThread build(){
return new GetPicThread(this);
}
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(6000);
if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
InputStream is = conn.getInputStream();
Bitmap bm = BitmapFactory.decodeStream(is);
Message msg = Message.obtain();//复用Message,使用Message.obtain()可以减少一直new Message造成的内存压力
msg.what = 1;
msg.obj = bm;
handler.sendMessage(msg);
is.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在MainActivity类中完成图片显示
完成实例化并接收GetPicThread类中传入的Handler
对象,将图片显示在对应的控件上
public class MainActivity extends AppCompatActivity {
private ImageView img;
private Button btn;
private String path = "https://img2.mukewang.com/5adfee7f0001cbb906000338-240-135.jpg";
private Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
Bitmap bm = (Bitmap) msg.obj;
img.setImageBitmap(bm);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = findViewById(R.id.img);
btn = findViewById(R.id.btn);
}
public void myClick(View v) {
switch (v.getId()) {
case R.id.btn:
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 通过建造者模式创建对象
// 可以把原本多行的xx.set()方法调用简化成链式调用
GetPicThread gpt = new GetPicThread.Builder()
.setPath(path)
.setHandler(handler).build();
new Thread(gpt).start();
}
});
break;
}
}
}
tips:
Handler
是Android提供用于更新UI的一套消息处理机制
创建Handler
的目的是完成对UI界面的处理,如显示图像、改变控件样式等等,子线程仅进行数据的传输、获取以及解析等处理,不涉及对界面控件的处理
Builder建造者模式
这里简单的尝试了一下建造者模式
一般来说当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,就可以考虑使用建造者模式
实现步骤
这里拿Student类举例,
Student类属性:
姓名name(必选)
学号id(必选)
年龄age(可选)
性别sex(可选)
- 在Student中创建一个静态内部类 Builder,然后将Student中的参数都复制到Builder类中。
- 在Student中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个public的构造函数,参数为类中必填的那些参数,name和id。
- 在Builder中创建设置函数,对Student中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个build()方法,在其中构建Student的实例并返回
示例代码
public class Student{
private String name;// 必选
private int id;// 必选
private int age;// 可选
private String sex;// 可选
private Student(Builder builder){
this.name = builder.name;
this.id = builder.id;
this.age = builder.age;
this.sex = builder.sex;
}
public static class Builder{
private String name;// 必选
private String id;// 必选
private int age;// 可选
private String sex;// 可选
public Builder(String name, String id){
this.name = name;
this.id = id;
}
public Builder setAge(int age){
this.age = age;
return this;
}
public Builder setSex(String sex){
this.sex = sex;
return this;
}
public Student build(){
return new Student(this);
}
}
}
使用方法
在实例化该类对象的时候,使用链式调用,一步一步把对象构建出来
Student student = new Student.Builder("张三","001")
.setAge(21)
.setSex("男")
.build();
这样就完成了对象的实例化操作