在开始学习联网的过程中,先接触的是从网络上获取图片的联网方式,在这里主要设计一个用户界面实现输入图片网址点击收索并实现下载显示功能。
用到的知识主要有2个
1.联网方法
2.异步任务实现
用户操作界面:
一、联网操作主要实现方法
1.URL为对网络地址的一种包装,接收内容为string类型
2.new出一个URL并对获取到的图片网址惊醒URL包装
3.通过URL方法调用openConnection()打开连接(打开连接的方法又很多种,本文使用的是HttpURLConnection方式)
4.通过此链接的方法设置请求方式(本文是由get)、设置超时时间、获取请求码
5.判断请求码若为200为请求正常否则为失败
6.请求成功后解析解析链接流获得图片,并将相应的图片设置到XML控件中去
7.声明权限
二、异步联网操作
由于下载联网等操作为耗时操作,故Android要求此类操作需在子线程(异步任务)中完成,故使用AsyncTask完成在子线程中的联网操作。
在Android中实现异步任务机制有两种方式,Handler和AsyncTask。
Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下。
为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。
先来看看AsyncTask的定义:
- public abstract class AsyncTask<Params, Progress, Result> {
三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。在特定场合下,并不是所有类型都被使用,如果没有被使用,可以用java.lang.Void类型代替。
一个异步任务的执行一般包括以下几个步骤:
1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
在使用的时候,有几点需要格外注意:
1.异步任务的实例必须在UI线程中创建。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。
现实代码
XML
<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="com.example.onlinetext.MainActivity" >
<ImageView
android:id="@+id/iv"
android:layout_weight="1000"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="http://p1.qq181.com/cms/1206/2012061814370042589.jpg"
/>
<Button
android:id="@+id/bt"
android:onClick="click"
android:text="搜索"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
mainactivity
package com.example.onlinetext;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import org.apache.http.client.methods.HttpOptions;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageView iv;
private EditText et_path;
@Override
//oncreate方法主要实现对xml中控件的引索
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
et_path = (EditText) findViewById(R.id.et_path);
}
//"click"是xml中对button定义的点击事件名,此方法的作用为实现点击事件实现联网下载图片的操作
public void click(View view) {
if (TextUtils.isEmpty(et_path.getText().toString().trim())) {
Toast.makeText(this, "地址不能为空", 0).show();
} else {
//Y由于下载联网等操作为耗时操作,故Android要求此类操作需在子线程(异步任务)中完成,故使用AsyncTask完成在子线程中的联网操作。
//三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。不是所有类型都被使用
AsyncTask<String, String, Bitmap> task = new AsyncTask<String, String, Bitmap>() {
@Override
//此方法为实现子线程操作并在后台运行的方法,当Execute()方法被调用,此方法内的操作运行,执行后将结果返回给result供onPostExecute调用
//doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。
//在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(et_path.getText().toString().trim());
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
//conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");
int code = conn.getResponseCode();
if (code == 200) {
Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
//onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if(result == null){
Toast.makeText(MainActivity.this, "获取图片失败", 0).show();
return;
}
iv.setImageBitmap(result);
}
};
//execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
task.execute("");
}
}
}