基础学习总结(七)--子线程及Handler

时间:2023-03-09 01:08:54
基础学习总结(七)--子线程及Handler

使用子线程获取网络图片
1.采用httpUrlConnection直连方式获取图片
2.采用子线程方式获取

 <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_icon"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1" /> <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <EditText android:id="@+id/et_url"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1" /> <Button android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="Go" /> </LinearLayout>
</LinearLayout>

线性布局

 public class MainActivity extends Activity implements OnClickListener {
private final int SUCESS = 0;
private final int ERROR=-1;
private EditText etUrl;
private ImageView ivIcon; private Handler hand=new Handler(){
/*
* 接收信息
* */
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what==SUCESS){//识别访问handle的程序集
ivIcon.setImageBitmap((Bitmap)msg.obj);//设置bitmap显示图片
}else if(msg.what==ERROR){
Toast.makeText(MainActivity.this, "抓取异常", 0).show();
}
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); ivIcon = (ImageView)findViewById(R.id.iv_icon);
etUrl = (EditText)findViewById(R.id.et_url); findViewById(R.id.btn_submit).setOnClickListener(this);
} @Override
public void onClick(View v) {
// TODO Auto-generated method stub
final String url=etUrl.getText().toString();
//Bitmap bitmap=getImageFormat(url);
//ivIcon.setImageBitmap(bitmap);//设置image显示图片
new Thread(new Runnable(){
@Override
public void run(){
Bitmap bitmap=getImageFormat(url);
if(bitmap!=null){
Message msg=new Message();
msg.what=SUCESS;//设置handle区别码
msg.obj=bitmap;//将二进制数据放入msg
hand.sendMessage(msg);
}else{
Message msg=new Message();
msg.what=ERROR;
hand.sendMessage(msg);
}
}
}).start(); } /**
* 根据url链接网络获取图片返回
* */
private Bitmap getImageFormat(String url){
HttpURLConnection conn=null;
try {
URL mUrl=new URL(url);
conn =(HttpURLConnection)mUrl.openConnection();
//设置传值方式
conn.setRequestMethod("GET");
//设置链接超时时间
conn.setConnectTimeout(10000);
//设置等待时间
conn.setReadTimeout(5000); conn.connect();
int code=conn.getResponseCode();//获得服务器响应对象
if(code==200){
//访问成功
InputStream is=conn.getInputStream();//获得服务器返回的二进制数据
Bitmap bitmap = BitmapFactory.decodeStream(is);//将二进制流转换为bitmap图片 return bitmap;
}else{
Log.i("MainActivity","链接不正常了...");
} } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(conn!=null){
conn.disconnect();
}
} return null;
} }

权限:<uses-permission android:name="android.permission.INTERNET"/>

在不使用子线程的方式下:等待超时后程序异常
addroid not responding(应用程序无响应)因子程序等待阻塞了主线程 ANR异常
异常:
CalledFrowWrongThreadException:Only the original thread that creaded a view hierarchy can touch its views
只有原始的线程(主线程或ui线程)才能修改view对象

handler处理过程

 public class MainActivity extends Activity {

     private EditText etUserName;
private EditText etPassword; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); etUserName = (EditText) findViewById(R.id.et_username);
etPassword = (EditText) findViewById(R.id.et_password);
} public void doGet(View v) {
final String userName = etUserName.getText().toString();
final String password = etPassword.getText().toString(); new Thread(
new Runnable() { @Override
public void run() {
// 使用get方式抓去数据
final String state = NetUtils.loginOfGet(userName, password); // 执行任务在主线程中
runOnUiThread(new Runnable() {
@Override
public void run() {
// 就是在主线程中操作
Toast.makeText(MainActivity.this, state, 0).show();
}
});
}
}).start();
} public void doPost(View v) {
final String userName = etUserName.getText().toString();
final String password = etPassword.getText().toString(); new Thread(new Runnable() {
@Override
public void run() {
final String state = NetUtils.loginOfPost(userName, password);
// 执行任务在主线程中
runOnUiThread(new Runnable() {
@Override
public void run() {
// 就是在主线程中操作
Toast.makeText(MainActivity.this, state, 0).show();
}
});
}
}).start();
}
}
 public class NetUtils {

     private static final String TAG = "NetUtils";

     /**
* 使用post的方式登录
* @param userName
* @param password
* @return
*/
public static String loginOfPost(String userName, String password) {
HttpURLConnection conn = null;
try {
URL url = new URL("http://10.0.2.2:8080/ServerItheima28/servlet/LoginServlet"); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST");
conn.setConnectTimeout(10000); // 连接的超时时间
conn.setReadTimeout(5000); // 读数据的超时时间
conn.setDoOutput(true); // 必须设置此方法, 允许输出
// conn.setRequestProperty("Content-Length", 234); // 设置请求头消息, 可以设置多个 // post请求的参数
String data = "username=" + userName + "&password=" + password; // 获得一个输出流, 用于向服务器写数据, 默认情况下, 系统不允许向服务器输出内容
OutputStream out = conn.getOutputStream();
out.write(data.getBytes());
out.flush();
out.close(); int responseCode = conn.getResponseCode();
if(responseCode == 200) {
InputStream is = conn.getInputStream();
String state = getStringFromInputStream(is);
return state;
} else {
Log.i(TAG, "访问失败: " + responseCode);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
conn.disconnect();
}
}
return null;
} /**
* 使用get的方式登录
* @param userName
* @param password
* @return 登录的状态
*/
public static String loginOfGet(String userName, String password) {
HttpURLConnection conn = null;
try {
String data = "username=" + URLEncoder.encode(userName) + "&password=" + URLEncoder.encode(password);
URL url = new URL("http://10.0.2.2:8080/ServerItheima28/servlet/LoginServlet?" + data);
conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // get或者post必须得全大写
conn.setConnectTimeout(10000); // 连接的超时时间
conn.setReadTimeout(5000); // 读数据的超时时间 int responseCode = conn.getResponseCode();
if(responseCode == 200) {
InputStream is = conn.getInputStream();
String state = getStringFromInputStream(is);
return state;
} else {
Log.i(TAG, "访问失败: " + responseCode);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
conn.disconnect(); // 关闭连接
}
}
return null;
} /**
* 根据流返回一个字符串信息
* @param is
* @return
* @throws IOException
*/
private static String getStringFromInputStream(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1; while((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
is.close(); String html = baos.toString(); // 把流中的数据转换成字符串, 采用的编码是: utf-8 // String html = new String(baos.toByteArray(), "GBK"); baos.close();
return html;
}
}

基础学习总结(七)--子线程及Handler