下面代碼設計了異步任務、JSon解析、自定義組件、IO流、文件下載、適配器原理等知識點。
代碼實現從服務器上讀取Json字符串。
Json字符串如下。
{object:{persons:[{name:'呵呵',image:'http://10.0.159.12:8080/Web/s1.png'},{name:'哈哈',image:'http://10.0.159.12:8080/Web/s1.png'},{name:'嘿嘿',image:'http://10.0.159.12:8080/Web/s2.jpg'}]}}
利用ListView控件將name和image圖片顯示出來。效果如圖:
思路(解析json字符串,然後再次讀取服務器上的圖片解析成byte[]格式。)
新建ImageInfo類存儲ListView顯示的數據:一個是顯示名字name屬性,一個圖片數據。
package com.example.day22_domain;
import java.util.Arrays;
public class ImageInfo {
private String name;
private byte[] imagebit;
public ImageInfo() {
super();
// TODO Auto-generated constructor stub
}
public ImageInfo(String name, byte[] imagebit) {
super();
this.name = name;
this.imagebit = imagebit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getImagebit() {
return imagebit;
}
public void setImagebit(byte[] imagebit) {
this.imagebit = imagebit;
}
@Override
public String toString() {
return "ImageInfo [name=" + name + ", imagebit="
+ Arrays.toString(imagebit) + "]";
}
}
寫了一個工具類用來解析Json數據和圖片:
package com.example.day22_tools;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.example.day22_domain.ImageInfo;
public class HttpUtils {
public HttpUtils() {
}
public static String getJsonString(String path)
{
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setDoInput(true);
if(conn.getResponseCode()==200)
{
InputStream inputStream = conn.getInputStream();
return changetToString(inputStream);
}
}catch(Exception e)
{
e.printStackTrace();
}
return null;
}
private static String changetToString(InputStream inputStream) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] arr = new byte[1024];
int len = 0;
try {
while((len = inputStream.read(arr))!=-1)
{
bos.write(arr,0,len);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] b = bos.toByteArray();
String ss = new String(b,0,b.length);
return ss;
}
public static List<ImageInfo> getImageInfo(String jsonString)
{
List<ImageInfo> list = new ArrayList<ImageInfo>();
try {
JSONObject obj = new JSONObject(jsonString);
JSONObject jsonObj = obj.getJSONObject("object");
JSONArray array = jsonObj.getJSONArray("persons");
for(int i=0;i<array.length();i++)
{
ImageInfo image = new ImageInfo();
JSONObject object = array.getJSONObject(i);
image.setName(object.getString("name"));
String imagepath=object.getString("image");
byte[] data=getImageByte(imagepath);
image.setImagebit(data);
list.add(image);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
public static byte[] getImageByte(String imagepath)
{
ByteArrayOutputStream bos=null;
try{
URL url=new URL(imagepath);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
if(conn.getResponseCode()==200)
{
InputStream inStream=conn.getInputStream();
bos = new ByteArrayOutputStream();
byte[] arr = new byte[1024];
int len = 0;
while((len = inStream.read(arr))!=-1)
{
bos.write(arr,0,len);
}
}
}catch(IOException e){
e.printStackTrace();
}
byte[] b = bos.toByteArray();
return b;
}
}
主界面:通過異步任務進行後臺下載圖片解析Json數據,然後顯示在自定義的ListView組件中。
<span style="font-size:14px;">package com.example.day22_all;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.example.day22_domain.ImageInfo;
import com.example.day22_tools.HttpUtils;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView listView;
private String path="http://10.0.159.12:8080/Web/servlet/JsonServlet";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
new DownText().execute(path);
}
class DownText extends AsyncTask<String, Integer, List<Map<String, Object>>>
{
@Override
protected List<Map<String,Object>> doInBackground(String... params) {
String jsonStr=HttpUtils.getJsonString(params[0]);
System.out.println("jsonStr"+jsonStr);
List<ImageInfo> list=HttpUtils.getImageInfo(jsonStr);
System.out.println("ImageInfo");
List<Map<String,Object>> imageinfo=new ArrayList<Map<String,Object>>();
for(int i=0;i<list.size();i++)
{
Map<String,Object> map=new HashMap<String, Object>();
String name=list.get(i).getName();
byte[] arr=list.get(i).getImagebit();
Bitmap bitMap = BitmapFactory.decodeByteArray(arr, 0, arr.length);
map.put("name", name);
map.put("bitmap", bitMap);
imageinfo.add(map);
}
return imageinfo;
}
@Override
protected void onPostExecute(List<Map<String,Object>> result) {
super.onPostExecute(result);
MyAdapter adapter = new MyAdapter(MainActivity.this,result);
listView.setAdapter(adapter);
}
class MyAdapter extends BaseAdapter
{
private Context context;
private List<Map<String, Object>> list;
public MyAdapter(Context context, List<Map<String,Object>> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView==null)
{</span>
<span style="font-size:14px;"> convertView = LayoutInflater.from(context).inflate(R.layout.other_image, nu
viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image);
viewHolder.textView = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(viewHolder);
}
else
viewHolder = (ViewHolder) convertView.getTag();
// viewHolder.imageView.setImageResource(Integer.parseInt(list.get(position).get("bitmap").toString()));
viewHolder.textView.setText(list.get(position).get("name").toString());
viewHolder.imageView.setImageBitmap((Bitmap)list.get(position).get("bitmap"));
return convertView;
}
class ViewHolder
{
ImageView imageView;
TextView textView;
}
}
}
}</span><span style="font-size:18px;">
</span>
註釋:
/*
在實際開發中LayoutInflater這個類還是非常有用的,它的作用類似於findViewById()。不同點是LayoutInflater是用來找res/layout/下的xml佈局文件,並且實例化;而findViewById()是找xml佈局文件下的具體widget控件(如Button、TextView等)。
具體作用:
1、對於一個沒有被載入或者想要動態載入的界面,都需要使用LayoutInflater.inflate()來載入;
2、對於一個已經載入的界面,就可以使用Activiyt.findViewById()方法來獲得其中的界面元素。
LayoutInflater 是一個抽象類,在文檔中如下聲明:
public abstract class LayoutInflater extends Object
獲得 LayoutInflater 實例的三種方式
1. LayoutInflater inflater = getLayoutInflater();//調用Activity的getLayoutInflater()
2. LayoutInflater inflater = LayoutInflater.from(context);
3. LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
其實,這三種方式本質是相同的,從源碼中可以看出:
getLayoutInflater():
Activity 的 getLayoutInflater() 方法是調用 PhoneWindow 的getLayoutInflater()方法,看一下該源代碼:
public PhoneWindow(Context context)
{
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
可以看出它其實是調用 LayoutInflater.from(context)。
LayoutInflater.from(context):
public static LayoutInflater from(Context context)
{
LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
if (LayoutInflater == null)
{
throw new AssertionError("LayoutInflater not found.");
}
return LayoutInflater;
}
可以看出它其實調用 context.getSystemService()。
結論:所以這三種方式最終本質是都是調用的Context.getSystemService()。
注意:
·inflate 方法與 findViewById 方法不同;
·inflater 是用來找 res/layout 下的 xml 佈局文件,並且實例化;
·findViewById() 是找具體 xml 佈局文件中的具體 widget 控件(如:Button、TextView 等)。
*/
寫一下佈局文件和服務器就好了:
activity_main.xml
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.day22_all.MainActivity" >
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
></ListView>
</RelativeLayout>
other_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
注意:要在清單文件中添加網絡訪問權限:
<uses-permission android:name="android.permission.INTERNET"/>