对Thread以及AsyncTask的理解整理

今天在写项目的时候,遇到了写引导页的需求,这个需求的实现想必是很简单的(还是老套路,大神请自觉略过大笑);

思路:
1. 创建一个guideActivity文件,需要在Manifest文件中将MainActivity进行替换并注册MainActivity,在xml文件中声明一个ImageView;
2. 明确该图片是从网络上加载的还是本地加载;
3. 明确引导页的作用(添加广告,延时跳转为我们app加载网络信息争取时间等等);

4. 因为提及延时这个词,所以第一时间想到线程;


如何去写引导页并不是重点,重点是当再次使用线程的时候,感觉知识点还是有一些模糊,所以打算重新对线程进行理解以下是我的整理:

1.明确线程的作用:提高程序的效率,将我们的阻塞操作(网络请求,数据库查询等)放到子线程中去执行,可以有效的防止UI线程(主线程)卡顿,这里需要注意,当UI程序被阻塞大约5s后会出现(应用无响应)ANR对话框 !

2.
new Thread(new Runnable() {
    @Override
    public void run() {
        Picasso.with(GuideActivity.this).load(imageUrl).into(guideIv);
    }
}).start();

以上的这段代码表面上已经解决了我们的问题,因为它通过子线程避免了阻塞,但是它却违背了单线程模式的第二条(不要在UI线程之外访问UI工具包,Android UI包并非线程的安全工具包.以上线程为工作线程,会出现不可预见的行为).因此Android提供了几种其他线程访问主线程的方式:

Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.PostDelayed(Runnable)
Handler

3.天真烂漫的我以为以上几种方式会解决我在android世界中遇到的所有的线程问题,但事实并不是如此,当遇到复杂操作,页面频繁更新的时候,我们的代码逻辑会变得复杂,可读性差,所以AsyncTask(异步)的横空出世,大大的简化了线程间的通信(这里要注意的是,AsyncTask是Android1.5出现的,但并不代表之前的Android1.1和1.0用不了,只是名字不同罢了"UserTask");

4.通过阅读API文档:我们可以得知,AsyncTask被设计为是Thread和Handler的辅助类,但是理想情况下,AsyncTask还是比较适合短操作(大概就几秒),如果要长时间保持线程运行,强烈建议java.util.concurrent包提供的API,例如ThreadPoolExecutorFutureTask;

AsyncTask由3个通用类型(Params, Process, Result)和4个步骤(onPreExecute, doInBackground, onProgressUpdate and onPostExecute)定义;

除了doInBackground方法在子线程中执行外,剩下的方法都在UI线程执行,且在doInBackground方法中可以随时调用publishProgress(),以在 UI 线程中执行onProgressUpdate();

5. 将上面的代码用AsyncTask改写并补充完整为:

public class MainActivity extends AppCompatActivity {

    private ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageView = (ImageView) findViewById(R.id.main_Iv);
        mImageView.setScaleType(ImageView.ScaleType.CENTER);

        // 当点击默认图片时,进行图片的切换
        mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 声明一个异步类对象
                DownloadTask downloadTask = new DownloadTask();
                // 将ImageView空间传递到异步类中
                downloadTask.setImageView(mImageView);
                // 执行异步操作(网址传递)
                downloadTask.execute("http://sjbz.fd.zol-img.com.cn/t_s320x510c/g5/M00/0F/0E/ChMkJ1fJSDKIFwPTAAvIx93CjoYAAU8twM39KkAC8jf384.png");
            }
        });


    }
}
 
public class DownloadTask extends AsyncTask<String, Void, Bitmap> {

    private ImageView mImageView;

    public void setImageView(ImageView imageView) {
        mImageView = imageView;
    }

    @Override
    protected Bitmap doInBackground(String... params) {

        try {
            // 进行网络请求(此处也可使用OkHttp进行网络请求)
            // 但是要注意的是发起请求的方法应该是 client.newCall(request).execute();
            // 而不是:
            //  client.newCall(request).enqueue(new Callback() {
            //      @Override
            //      public void onFailure(Call call, IOException e) {
            //
            //      }
            //  }
            // 正如你所看到的,该方法会再开一个线程,导致创建Bitmap的时候出现报空行为

            URL url = new URL(params[0]);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            InputStream is = conn.getInputStream();
            return BitmapFactory.decodeStream(is);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        // 将网络解析下来的数据设置到控件上
        mImageView.setImageBitmap(bitmap);
    }
}
 
效果展示:


点击图标后:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值