Android自定義組件ListView

下面代碼設計了異步任務、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"/>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章