网络图片查看器
|
核心代码: package cn.zengfansheng.imageview;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_url;
private ImageView iv_image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_image = (ImageView) this.findViewById(R.id.iv_image);
et_url = (EditText) this.findViewById(R.id.et_url);
}
/**
* 点击查看图片
*
* @param view
*/
public void viewImage(View view) {
new Thread() { // 重新创建一个Thread类处理请求网络的连接
@Override
public void run() {
// 原因: 访问网络 耗时的操作 需要一定的时间 为了避免界面卡死 无响应 4.0系统做了一个处理
// 所有的网络访问的操作 是不可以在主线程里面执行.
try {
// 1、获取用户输入的url
String url = et_url.getText().toString();
if (TextUtils.isEmpty(url)) {
Toast.makeText(MainActivity.this, "图片url不能为空。。。", 0)
.show();
return;
}
// 2、将地址包装成url
URL imageUrl = new URL(url);
// 3、获取一个HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) imageUrl
.openConnection();
// 4、设置请求头信息
conn.setRequestMethod("GET");// 设置http的请求方式 get / post 注意单词
// 大写
conn.setConnectTimeout(5000);// 连接两秒超时
conn.setReadTimeout(5000);// 读取两秒超时
String userAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)";
conn.setRequestProperty("User-Agent", userAgent);
// 5、获取服务器返回信息
int code = conn.getResponseCode();
if (code == 200) { // 返回正确码
InputStream in = conn.getInputStream();// 得到服务器返回的输入流
Bitmap bitmap = BitmapFactory.decodeStream(in);
iv_image.setImageBitmap(bitmap);
} else {
Toast.makeText(MainActivity.this, "请求失败", 0).show();
}
} catch (MalformedURLException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "获取图片失败", 0).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "获取图片失败", 0).show();
}
}
}.start();
}
}
结果:(但还是有问题3,)
|
问题1:访问网络 耗时的操作 需要一定的时间 为了避免界面卡死 无响应 4.0系统做了一个处理 // 所有的网络访问的操作 是不可以在主线程里面执行.
10-14 12:29:31.336: E/AndroidRuntime(24430): Caused by: android.os.NetworkOnMainThreadException
|
问题2:权限 10-14 12:39:21.748: E/AndroidRuntime(25369): java.lang.SecurityException: Permission denied (missing INTERNET permission?)
|
问题3:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 只有主线程才能更新UI操作 在android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示。但是, 在主线线程之外的线程中直接更新页面显示的问题是: 系统会报这个异常,android.view.viewroot$calledfromwrongthreadexception: only the original thread that created a view hierarchy can touch its views. (只有原始创建这个视图层次(view hierachy)的线程才能修改它的视图(view)。)。 也就是说必须在程序的主线程(也就是ui线程)中进行更新界面显示的工作。可以采用下面的方法之一来解决: 解决方案1:在activity.oncreate(bundle savedinstancestate)中创建一个handler类的实例, 在这个handler实例的handlemessage回调函数中调用更新界面显示的函数。例如:
在其它的函数中,利用 send族或post族函数向这个h发送或邮寄消息即可。 解决方案2:利用activity.runonuithread(runnable) 把更新ui的代码创建在runnable中,然后在需要更新ui时,把这个runnable对象传给activity.runonuithread(runnable)。 这样runnable对像就能在ui程序中被调用。
|
问题4:10-14 16:58:13.065: E/AndroidRuntime(4876): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 原因:不能创建handler,在没有调用Looper.loop()之前
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
iv_image.setImageBitmap(bitmap);
}
};
handler.sendEmptyMessage(0);
这是由于在子线程中创建Handler
|