一、ListView分頁加載java
<1>分頁的做用android
(1)避免一次性加載過多內容時,形成內存溢出;json
(2)能夠加強用戶體驗。網絡
<2>實現思路數據結構
(1)當滾動到最後一條的時候,加載新數據;app
(2)適配器的數據源要進行累加:listDatas.addAll(list)異步
(3)數據發生變化時,適配器及時通知:adapter.notifyDataSetChanged()ide
(4)判斷是否滾到了最後一行工具
if (firstVisibleItem + visibleItemCount == totalItemCount ) { isBottom = true; }
<3>實例步驟佈局
(1)模擬1000條數據,以分頁方式顯示;
(2)使用BaseAdapter自定義適配器顯示數據;
(3)在ListView下方增長「顯示更多」按鈕以實現加載下一頁數據;
(4)ListView.setOnScrollListener()方法設置滾動事件監聽器;
(5)經過滾動事件監聽器判斷是否滾動到最底部,若在底部則顯示「顯示更多「按鈕;
(6)點擊「顯示更多」按鈕,根據當前的頁碼與一頁顯示的記錄數,加載數據;
(7)將加載的數據追加到適配器的數據源中
二、AdapterView.OnItemClickListener 列表項點擊事件監聽器:onItemClick(AdapterView<?> parent, View view, int position, long id)
三、OnScrollListener 滾動事件監聽器
<1>onScrollStateChanged(AbsListView view, int scrollState):監聽屏幕的滾動狀態的變更狀況
(1)scrollState狀態說明:
SCROLL_STATE_TOUCH_SCROLL(1):
表示正在滾動。當屏幕滾動且用戶使用的觸碰或手指還在屏幕上時爲1
SCROLL_STATE_FLING(2) :
表示手指作了拋的動做(手指離開屏幕前,用力滑了一下,屏幕產生慣性滑動)。
SCROLL_STATE_IDLE(0) :
表示屏幕已中止。屏幕中止滾動時爲0。
<2>onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount):監聽屏幕滾動的item的數量
(1)AbsListView : 當前滾動的ListView控件
(2)firstVisibleItem:當前窗口中能看見ListView的第一個列表項ID(從0開始)
(3)visibleItemCount:當前窗口中能看見的ListView列表項的個數(小半個也算)
(4)totalItemCount:ListView列表項的總數
四、ListView的優化
<1>ListView的高度屬性設置
(1)設置爲"wrap_content"時,getView()方法通常會執行3次左右;
(2)建議設置爲"match_parent"或固定值,避免重複計算ListView的高度。
<2>ViewHolder的使用,將findViewById()獲取的控件封裝起來,便於複用
<3>convertView的複用
(1)converView如何產生的?
Android中有個叫作Recycler的構件,下圖是他的工做原理:
a、若是你有100個item,其中只有可見的項目存在內存中,其餘的在Recycler中。
b、ListView先請求一個type1視圖(getView),而後請求其餘可見的item,convertView在getView中是空(null)的。
c、當item1滾出屏幕,而且一個新的item從屏幕底端上來時,ListView再請求一個type1視圖,convertView此時不是空值了,它的值是item1。你只需設定新的數據,而後返回convertView,沒必要從新建立一個視圖。
(2)優勢:減小getView()時經過infalter加載佈局的次數,減小內存開銷,提升性能
(3)缺點:若使用異步任務下載圖片時,可能會出現圖片錯位問題,由於convertView的位置多是第一個
<4>View的標籤tag屬性
(1)同id屬性同樣,標識控件的惟一性
(2)View.setTag(Object)設置控件的標籤
(3)View.getTag()獲取控件的標籤
(4)View.setTag()+ViewHolder+convertView複用,減小布局加載和findViewBy的次數,下降的內存開銷,提高性能
五、ListView實現圖文混排
<1>實現思路
(1)建立圖文混排的Item佈局文件
<?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="vertical" > <ImageView android:id="@+id/img" android:layout_width="80dp" android:layout_height="80dp" android:scaleType="fitXY" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tv_address" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_age" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
(2)根據JSON的數據結構構建實體類
package com.qf.bean; public class Girl { private String address; private int age; private String avatar; private String name; private String phone; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAvatar() { return avatar; } public void setAvatar(String avatar) { this.avatar = avatar; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "Girl [address=" + address + ", age=" + age + ", avatar=" + avatar + ", name=" + name + ", phone=" + phone + "]"; } }
(3)建立BaseAdapter的子類,並實現相關方法
package com.qf.adapter; import java.util.List; import com.qf.asy.ImgAsy; import com.qf.bean.Girl; import com.qf.day10demo02.R; import com.qf.util.Constant; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class GirlAdapter extends BaseAdapter{ private List<Girl> data; private Context context; public GirlAdapter(List<Girl> data, Context context) { super(); this.data = data; this.context = context; } @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { viewHolder = new ViewHolder(); convertView = LayoutInflater.from(context).inflate(R.layout.item, null); viewHolder.img = (ImageView) convertView.findViewById(R.id.img); viewHolder.tv_address = (TextView) convertView.findViewById(R.id.tv_address); viewHolder.tv_age = (TextView) convertView.findViewById(R.id.tv_age); viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name); viewHolder.tv_phone = (TextView) convertView.findViewById(R.id.tv_phone); convertView.setTag(viewHolder); }else { viewHolder = (ViewHolder) convertView.getTag(); } Girl girl = data.get(position); //拿到圖片的後半段地址 String avatar = girl.getAvatar(); viewHolder.img.setTag(Constant.BASE_URL + avatar); //下載圖片地址 new ImgAsy(viewHolder.img).execute(Constant.BASE_URL + avatar); viewHolder.tv_address.setText(girl.getAddress()); viewHolder.tv_age.setText(girl.getAge() +""); viewHolder.tv_name.setText(girl.getName()); viewHolder.tv_phone.setText(girl.getPhone()); return convertView; } class ViewHolder{ ImageView img; TextView tv_address,tv_age,tv_name,tv_phone; } }
(4)建立網絡工具類
package com.qf.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class NetworkUtil { public static byte[] getBytes(String path){ InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(path); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(3000); if (200 == connection.getResponseCode()) { is = connection.getInputStream(); baos = new ByteArrayOutputStream(); int len = 0; byte[] buffer = new byte[1024]; while((len = is.read(buffer)) != -1){ baos.write(buffer,0,len); } return baos.toByteArray(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(baos != null){ try { baos.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }
(5)建立AsyncTask的子類並實現網絡請求和JSON解析的功能
package com.qf.asy; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.qf.bean.Girl; import com.qf.util.NetworkUtil; import android.content.Context; import android.os.AsyncTask; import android.widget.Toast; public class DataAsy extends AsyncTask<String, Void, List<Girl>>{ private DataCallback callback; private Context context; public DataAsy(DataCallback callback, Context context) { super(); this.callback = callback; this.context = context; } @Override protected List<Girl> doInBackground(String... params) { byte[] bytes = NetworkUtil.getBytes(params[0]); if (bytes != null) { String content = new String(bytes); //Log.i("info", "=====content===="+content); try { JSONObject object = new JSONObject(content); JSONArray array = object.optJSONArray("girls"); List<Girl> girlList = new ArrayList<Girl>(); Girl girl = null; //optxxx:當key值不存在的時候,程序不會崩,而是獲取一個類型的默認值 for (int i = 0; i < array.length(); i++) { JSONObject object2 = array.optJSONObject(i); girl = new Girl(); girl.setAddress(object2.optString("address")); girl.setAge(object2.optInt("age")); girl.setAvatar(object2.optString("avatar")); girl.setName(object2.optString("name")); girl.setPhone(object2.optString("phone")); girlList.add(girl); } return girlList; } catch (JSONException e) { e.printStackTrace(); } } return null; } @Override protected void onPostExecute(List<Girl> result) { super.onPostExecute(result); if (result == null) { Toast.makeText(context, "downLoad failed", Toast.LENGTH_LONG).show(); }else { callback.doResult(result); } } //聲明一個接口 public interface DataCallback{ public void doResult(List<Girl> result); } }
(6)6、將解析的數據傳入到自定義BaseAdapter適配器,並顯示到ListView
package com.qf.day10demo02; import java.util.ArrayList; import java.util.List; import com.qf.adapter.GirlAdapter; import com.qf.asy.DataAsy; import com.qf.asy.DataAsy.DataCallback; import com.qf.bean.Girl; import com.qf.util.Constant; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.Button; import android.widget.ListView; public class MainActivity extends Activity implements OnScrollListener,OnClickListener{ private ListView listView; private Button btn_more; private GirlAdapter adapter; private List<Girl> totaList = new ArrayList<Girl>(); private int page = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); btn_more = (Button) findViewById(R.id.btn_more); listView.setOnScrollListener(this); btn_more.setOnClickListener(this); getData(); adapter = new GirlAdapter(totaList, this);//空數據源 listView.setAdapter(adapter); } private void getData(){ new DataAsy(new DataCallback() { @Override public void doResult(List<Girl> result) { totaList.addAll(result); adapter.notifyDataSetChanged(); } },this).execute(Constant.INDEX_PATH+page); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem + visibleItemCount == totalItemCount) { btn_more.setVisibility(View.VISIBLE); }else { btn_more.setVisibility(View.GONE); } } @Override public void onClick(View v) { page++; getData(); } }
<2>須要的核心類
(1)BaseAdapter
(2)AsyncTask
(4)HttpClient
(5)JSONObject/JSONArray
六、listview其餘方法
<1>listView.addHeaderView(view);
View headView = LayoutInflater.from(this).inflate(R.layout.headlayout, null); //添加一個頭部佈局/控件,要在綁定適配器以前。 listView.addHeaderView(headView);
<2>listView.addFooterView(button);
Button button = new Button(this); button.setText("底部按鈕"); //添加一個底部佈局/控件 listView.addFooterView(button);
<3>listView.setEmptyView(emptyView);
TextView emptyView = (TextView) findViewById(R.id.emptyView); //使用前提:emptyView必須是預先存在當前佈局裏面,隱藏的 listView.setEmptyView(emptyView);