今天在写项目的时候,遇到了写引导页的需求,这个需求的实现想必是很简单的(还是老套路,大神请自觉略过
);
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
思路:
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,例如ThreadPoolExecutor和FutureTask;
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); } }
效果展示:
点击图标后: