android学习——handler的学习及实现封装下载图片功能
2016-04-13 23:45
513 查看
在初学handler的时候不得不说自己当时真是毫无悟性,硬是把handler和开通子线程混为一谈,当时脑子混乱的不行,也是看了一些博客后理清了头脑。
android是不允许在主线程中进行耗时操作的,否则会报错,出现ANR(Application Not Responding)现象,这时候必须开一个子线程,此时是不需要必须有handler的,而如果我们在子线程中去操作UI,那么程序就回给我们抛出异常。这时候我们就需要在子线程中通过handler来更新UI。
现在小小总结一下,自己都觉得可笑。
现在通过一个点击按钮下载一张图片的demo来详解一下handler。
Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,所以Handler把压入消息队列有两大体系,Post和Message。
Post
对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般在这个run()方法中写入需要在UI线程上的操作。
在Handler中,关于Post方式的方法有:
boolean post(Runnable r):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,立即执行。
boolean postAtTime(Runnable r,long uptimeMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,在特定的时间执行。
boolean postDelayed(Runnable r,long delayMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,延迟delayMills秒执行
void removeCallbacks(Runnable r):从消息队列中移除一个Runnable对象。
Message
Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重 写handleMessage()方法,用于获取工作线程传递过来的消息,此方法运行在UI线程上。
对于Message对象,一般使用Message.obtain()这个静态的方法或者 Handler.obtainMessage()获取。Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的,
才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。并不需要担心消息池中的消息过多,它是有上限的,上限为10个。 Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是 调用的Message.obtain()。
Message.obtain()方法具有多个重载方法,大致可以分为为两类,一类是无需传递Handler对象,对于这类的方法,当填充好消息后,需要调用Handler.sendMessage()方法来发送消息到消息队列中。第二类需要传递一个Handler对象,这类方法可以直接使用 Message.sendToTarget()方法发送消息到消息队列中,这是因为在Message对象中有一个私有的Handler类型的属性 Target,当时obtain方法传递进一个Handler对象的时候,会给Target属性赋值,当调用sendToTarget()方法的时候,实
际在它内部还是调用的Target.sendMessage()方法。
Handler中,与Message发送消息相关的方法有:<
4000
/p>
Message obtainMessage():获取一个Message对象。
boolean sendMessage():发送一个Message对象到消息队列中,并在UI线程取到消息后,立即执行。
boolean sendMessageDelayed():发送一个Message对象到消息队列中,在UI线程取到消息后,延迟执行。
boolean sendEmptyMessage(int what):发送一个空的Message对象到队列中,并在UI线程取到消息后,立即执行。
boolean sendEmptyMessageDelayed(int what,long delayMillis):发送一个空Message对象到消息队列中,在UI线程取到消息后,延迟执行。
void removeMessage():从消息队列中移除一个未响应的消息。
Handler的基本介绍差不多就是这些,接下来上代码,进行了封装:
DownloadContent.java
MainActivity:
贴一下用POST和HttpURLConnection的方法,这里没有用到封装,直接在一个Activity钟写的:
android是不允许在主线程中进行耗时操作的,否则会报错,出现ANR(Application Not Responding)现象,这时候必须开一个子线程,此时是不需要必须有handler的,而如果我们在子线程中去操作UI,那么程序就回给我们抛出异常。这时候我们就需要在子线程中通过handler来更新UI。
现在小小总结一下,自己都觉得可笑。
现在通过一个点击按钮下载一张图片的demo来详解一下handler。
Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,所以Handler把压入消息队列有两大体系,Post和Message。
Post
对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般在这个run()方法中写入需要在UI线程上的操作。
在Handler中,关于Post方式的方法有:
boolean post(Runnable r):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,立即执行。
boolean postAtTime(Runnable r,long uptimeMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,在特定的时间执行。
boolean postDelayed(Runnable r,long delayMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,延迟delayMills秒执行
void removeCallbacks(Runnable r):从消息队列中移除一个Runnable对象。
Message
Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重 写handleMessage()方法,用于获取工作线程传递过来的消息,此方法运行在UI线程上。
对于Message对象,一般使用Message.obtain()这个静态的方法或者 Handler.obtainMessage()获取。Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的,
才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。并不需要担心消息池中的消息过多,它是有上限的,上限为10个。 Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是 调用的Message.obtain()。
Message.obtain()方法具有多个重载方法,大致可以分为为两类,一类是无需传递Handler对象,对于这类的方法,当填充好消息后,需要调用Handler.sendMessage()方法来发送消息到消息队列中。第二类需要传递一个Handler对象,这类方法可以直接使用 Message.sendToTarget()方法发送消息到消息队列中,这是因为在Message对象中有一个私有的Handler类型的属性 Target,当时obtain方法传递进一个Handler对象的时候,会给Target属性赋值,当调用sendToTarget()方法的时候,实
际在它内部还是调用的Target.sendMessage()方法。
Handler中,与Message发送消息相关的方法有:<
4000
/p>
Message obtainMessage():获取一个Message对象。
boolean sendMessage():发送一个Message对象到消息队列中,并在UI线程取到消息后,立即执行。
boolean sendMessageDelayed():发送一个Message对象到消息队列中,在UI线程取到消息后,延迟执行。
boolean sendEmptyMessage(int what):发送一个空的Message对象到队列中,并在UI线程取到消息后,立即执行。
boolean sendEmptyMessageDelayed(int what,long delayMillis):发送一个空Message对象到消息队列中,在UI线程取到消息后,延迟执行。
void removeMessage():从消息队列中移除一个未响应的消息。
Handler的基本介绍差不多就是这些,接下来上代码,进行了封装:
DownloadContent.java
<span style="font-size:14px;">public class DownloadContent { private ProgressDialog dialog; private static int IS_FINISH = 1; public DownloadContent(Context context) { dialog = new ProgressDialog(context); dialog.setTitle("提示"); dialog.setMessage("正在玩命加载数据......"); } @SuppressLint("HandlerLeak") public void downLoad(final String path, final DownloadCallback callback) { final Handler handler = new Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); byte[] result = (byte[]) msg.obj; callback.loadContent(result); if (msg.what == IS_FINISH) { dialog.dismiss(); } } }; </span>
<span style="font-size:14px;">/*开通子线程有两种方法:<span style="font-family: verdana, 'ms song', Arial, Helvetica, sans-serif;">用 Runnable 或者 Thread </span><p>创建线程哪种方式更好呢?什么情况下使用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类,当然是调用Runnable接口更好了。*/</p> //调用Runnable接口,写法一 // class MyThread implements Runnable { // @Override //public void run() { // HttpClient httpClient = new DefaultHttpClient(); // HttpGet httpGet = new HttpGet(path); // HttpResponse response; // try { // response = httpClient.execute(httpGet); // if (response.getStatusLine().getStatusCode() == 200) { // byte[] result = EntityUtils.toByteArray(response // .getEntity()); // Message message = Message.obtain(); // message.obj = result; // message.what = IS_FINISH; // handler.sendMessage(message); // } // } catch (Exception e) { // // e.printStackTrace(); // } finally { // httpClient.getConnectionManager().shutdown(); // } //} //} //new Thread(new MyThread()).start();</span>
</pre><pre name="code" class="java"><span style="font-size:14px;"><pre name="code" class="java" style="color: rgb(57, 57, 57); font-size: 14px; line-height: 21px;"> /*<span style="font-family: verdana, 'ms song', Arial, Helvetica, sans-serif;">调用Runnable接口,写法二</span></span>
<span style="font-size:14px;"> new Thread() { public void run() { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(path); HttpResponse response; try { response = httpClient.execute(httpGet); if (response.getStatusLine().getStatusCode() == 200) { byte[] result = EntityUtils.toByteArray(response .getEntity()); Message message = Message.obtain(); message.obj = result; message.what = IS_FINISH; handler.sendMessage(message); } } catch (Exception e) { e.printStackTrace(); } finally { httpClient.getConnectionManager().shutdown(); } }; }.start();*/</span>
<span style="font-size:14px;">//继承Thread</span>
<span style="font-size:14px;"> class MyThread extends Thread{ public void run() { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(path); HttpResponse response; try { response = httpClient.execute(httpGet); if (response.getStatusLine().getStatusCode() == 200) { byte[] result = EntityUtils.toByteArray(response .getEntity()); Message message = Message.obtain(); message.obj = result; message.what = IS_FINISH; handler.sendMessage(message); } } catch (Exception e) { e.printStackTrace(); } finally { httpClient.getConnectionManager().shutdown(); } }; } MyThread myThread = new MyThread(); myThread.start(); </span>
<span style="font-size:14px;"> dialog.show(); } public interface DownloadCallback { public void loadContent(byte[] result); } }</span>
MainActivity:
<span style="font-size:14px;">public class MainActivity extends ActionBarActivity { private final String pathString = "http://attachments.gfan.com/forum/attachments2/day_120709/120709183388fdedffcd0878e9.jpg"; private Button button; private ImageView image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.btn); image = (ImageView) findViewById(R.id.img); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DownloadContent donwContent = new DownloadContent(MainActivity.this); donwContent.downLoad(pathString, new DownloadCallback() { @Override public void loadContent(byte[] result) { Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); image.setImageBitmap(bitmap); } }); } }); } }</span>
贴一下用POST和HttpURLConnection的方法,这里没有用到封装,直接在一个Activity钟写的:
<span style="font-size:14px;">public class PostActivity extends Activity { private Button btn; private ImageView img; private ProgressDialog dialog; private static Handler handler = new Handler(); private String path="http://img5.imgtn.bdimg.com/it/u=3829988479,3729798728&fm=21&gp=0.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); img = (ImageView) findViewById(R.id.img); dialog = new ProgressDialog(getApplicationContext()); dialog.setTitle("提示"); dialog.setMessage("正在努力下载"); dialog.setCancelable(false); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new MyThread()).start(); } }); } public class MyThread implements Runnable{ private Bitmap bitmap; private InputStream is; public void run(){ try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); int code = conn.getResponseCode(); if(code==200){ is = conn.getInputStream(); bitmap = BitmapFactory.decodeStream(is); handler.post(new Runnable() { public void run() { img.setImageBitmap(bitmap); } }); } } catch (IOException e) { e.printStackTrace(); } } } }</span>
相关文章推荐
- Android启动器停止运行的调试
- Android学习记录(四) 只在当前应用有效的数据库实现。
- Android 手把手教您自定义ViewGroup(一)
- android 从相册中获取图片
- android事件的分发和消费机制(onTouchEvent())
- Android开发:ListView控件:Your content must have a ListView whose id attribute is'android.R.id.list'
- Android开发基础第一章——Activity
- Android VectorDrawable SVG矢量图 xml格式
- Android Service详解
- AS插件-android-selector-chapek
- Android 自定义View (四) 视频音量调控
- Android 利用SurfaceView实现一个简单的计时器
- Android 自定义View (三) 圆环交替 等待效果
- Vs2015新建Android程序启动调试无响应
- Android开发系列(十一) QQ登陆界面——Android控件使用实例
- Android 自定义View (二) 进阶
- android Handler使用
- android实现不同样式的日历控件(MaterialCalendarView的改造工程)
- Android View框架的measure机制
- Android各个版本API的区别