Android第四十天

一、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);
相關文章
相關標籤/搜索