Android -- 网络图片查看器,网络html查看器, 消息机制, 消息队列,线程间通讯
1. 原理图
2. 示例代码 (网络图片查看器)
(1) HttpURLConnection
(2) SmartImageView (开源框架:https://github.com/loopj/android-smart-image-view)
Handler 类, 消息队列处理
访问互联网需要权限
<uses-permission android:name="android.permission.INTERNET"/>
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <ImageView android:id="@+id/iv_image" android:layout_weight="100" android:layout_width="match_parent" android:layout_height="0dp" /> <EditText android:id="@+id/et_path" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/link" android:hint="输入网络链接" /> <Button android:id="@+id/bt_link" android:onClick="click" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="查看" /> </LinearLayout>
MainActivity.java
package com.kevin.netimageview; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import javax.net.ssl.HttpsURLConnection; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.Menu; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { protected static final int CHANGE_UI = 0; protected static final int ERROR = 1; protected static final int LINK = 2; private EditText et_path; private ImageView iv_image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_path = (EditText) findViewById(R.id.et_path); iv_image = (ImageView) findViewById(R.id.iv_image); } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg){ //消息处理 if(msg.what==CHANGE_UI){ Toast.makeText(getApplicationContext(), "CHANGE_UI", Toast.LENGTH_SHORT).show(); Bitmap bitmap = (Bitmap) msg.obj; iv_image.setImageBitmap(bitmap); }else if(msg.what==ERROR){ Toast.makeText(getApplicationContext(), "发生ERROR", Toast.LENGTH_SHORT).show(); } else if(msg.what==LINK){ Toast.makeText(getApplicationContext(), "将要获取响应", Toast.LENGTH_SHORT).show(); } } }; public void click(View v){ new Thread(){ public void run(){ String path = et_path.getText().toString().trim(); if(path==null || path.length()==0){ Message msg = new Message(); msg.what = ERROR; handler.sendMessage(msg); return; } System.out.println("xxxxx"); try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求方式 为 GET conn.setRequestMethod("GET"); // 设置请求超时时间 conn.setConnectTimeout(5000); // 注意: 下面的读取超时的时间. // conn.setReadTimeout(timeoutMillis); conn.setRequestProperty( "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727)"); Message msg = new Message(); msg.what = LINK; handler.sendMessage(msg); // 把get请求发送出去,获取服务器上的数据 // 获取服务器的返回码 状态码 int code = conn.getResponseCode(); if(code == 200){ InputStream is = conn.getInputStream(); Bitmap bitMap = BitmapFactory.decodeStream(is); msg = new Message(); msg.what = CHANGE_UI; msg.obj = bitMap; handler.sendMessage(msg); //发送消息 } } catch (Exception e) { e.printStackTrace(); Message msg = new Message(); msg.what = ERROR; handler.sendMessage(msg); //发送消息 } } }.start(); } }
(2)SmartImageView 使用开源框架
main.xml 布局文件ImageView 改成 SmartImageView即可, 需要引用类的全路径
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <com.loopj.android.image.SmartImageView android:id="@+id/siv_image" android:layout_weight="100" android:layout_width="match_parent" android:layout_height="0dp" /> <EditText android:id="@+id/set_path" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/link" android:hint="输入网络链接" /> <Button android:id="@+id/sbt_link" android:onClick="click2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="查看" /> </LinearLayout>
MainActivity.java中直接操作 SmartImageView即可,
public void click2(View v){ SmartImageView iv_image = (SmartImageView) findViewById(R.id.siv_image); String url = et_path.getText().toString().trim(); //可以加入两张图片,分别在loading和获取文件失败的时候显示出来 iv_image.setImageUrl(url, R.drawable.ic_launcher, R.drawable.ic_launcher); Toast.makeText(this, "显示网络图片", Toast.LENGTH_SHORT).show(); }
3. 示例代码 (网络html查看器)
原理和2的代码相似, 不过要注意乱码问题的处理
MainActivity.java
public class MainActivity extends Activity { protected static final int PATH_CANOT_NULL = 1; protected static final int GET_HTML_ERROR = 2; protected static final int SET_TEXT = 3; private TextView tv_content; private EditText et_path; //在主线程创建一个消息处理器 private Handler handler = new Handler(){ //当解析到新的消息时候的处理方法 @Override public void handleMessage(Message msg) { //当有新的消息到来时候的处理方法 switch (msg.what) { case PATH_CANOT_NULL: Toast.makeText(getApplicationContext(), "路径不能为空", 1).show(); break; case GET_HTML_ERROR: Toast.makeText(getApplicationContext(), "获取html失败", 1).show(); break; case SET_TEXT: String text = (String) msg.obj;//重新获取到消息对象里面的文本 tv_content.setText(text); break; } super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_content = (TextView) findViewById(R.id.tv_content); et_path = (EditText) findViewById(R.id.et_path); } public void viewHtml(View view) { //子线程 new Thread() { public void run() { String path = et_path.getText().toString().trim(); if (TextUtils.isEmpty(path)) { //Toast.makeText(MainActivity.this, "路径不能为空", 1).show(); System.out.println("路径不能为空"); Message msg = new Message(); msg.what = PATH_CANOT_NULL; //指定消息的类型 一般用一个int类型的数据 区分不同的消息 handler.sendMessage(msg); return; } try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); Thread.sleep(5000);// 模拟一个网络访问的延迟 int code = conn.getResponseCode(); if (code == 200) { InputStream is = conn.getInputStream(); String text = StreamTools.readFromStream(is); //tv_content.setText(text); Message msg = new Message(); msg.what = SET_TEXT; //指定消息的类型 一般用一个int类型的数据 区分不同的消息 msg.obj = text;//把要传递的数据 放在这个消息里面 handler.sendMessage(msg); } else { //Toast.makeText(MainActivity.this, "获取html失败", 0).show(); System.out.println("获取html失败"); Message msg = new Message(); msg.what = GET_HTML_ERROR; //指定消息的类型 一般用一个int类型的数据 区分不同的消息 handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); //Toast.makeText(MainActivity.this, "获取html失败", 0).show(); System.out.println("获取html失败"); Message msg = new Message(); msg.what = GET_HTML_ERROR; //指定消息的类型 一般用一个int类型的数据 区分不同的消息 handler.sendMessage(msg); } }; }.start(); } }
StreamTools.java 工具类, 将InputStream转换为String
public class StreamTools { /** * 工具方法 把流里面的内容 转化成 String 字符串 * @param is 输入流 * @return String 字符串 * @throws IOException */ public static String readFromStream(InputStream is) throws Exception{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer))!=-1){ baos.write(buffer, 0, len); } is.close(); String result = baos.toString(); if(result.contains("gb2312")){ // result.getbytes("utf-8") byte[] temp = baos.toByteArray(); result = new String(temp, "gb2312"); } baos.close(); return result; } }