(一)ListView的分页
分页的必要性:实际开发中数据量往往都比较大 一次查询太多数据 效率比较低 界面也无法展示那么多数据。
使用分页展示数据
http://1000phone.net:8088/app/iAppFree/api/free.php?page=1&number=20
1.pageIndex url里面的page 想要展示第几页数据
2.pageSize url里面的number 每页展示几条数据
url地址的规范 地址与参数之间使用?隔开 多个参数之间用&(&&)隔开
使用按钮分页: 上一页 下一页 两个按钮
当点击下一页的时候 重新使用MyAsyncTask查询网络数据
滚动分页:1.给listView添加滚动的监听事件 理解监听事件中的两个方法
给listView添加滚动的监听事件 当我们鼓动listView的时候 它有三种状态
public static int SCROLL_STATE_IDLE = 0; //停顿的
public static int SCROLL_STATE_TOUCH_SCROLL = 1; //触摸滚动
public static int SCROLL_STATE_FLING = 2; //猛冲
滑动到末尾加载新数据的条件
1、当状态是SCROLL_STATE_IDLE (停顿的时候)加载新数据
2、滑动最底部
//firstVisibleItem 第一个可见条目 (position)
//visibleItemCount 可见的条目总数
//totalItemCount 总条目数
当第一条可见+ 可见的条目总数 = 总条目数 意味着滑动到最底部
(二)解决复用convertView出现的一些问题
例如:复选框选择错位 图片加载错位
编写
activity_main.xml 添加一个ListView
MainActivity.java 适配器控件使用的五个步骤
MyAdapter
getCount()
getView();
条目布局
ViewHolder
MyAsyncTask
doInBackgroud()
HttpUtils
onPostExecute()
JsonUtils
ImageAsyncTask
doInBackgroud()
HttpUtils
onPostExecute()
imageView.setImageBitmp(bm);
注意: ImageAsyncTask写完之后是在自定义适配器(MyAdapter)中调用
分页:
1.listView添加监听器 实现两个对滚动监听的方法
2.根据两个方法的参数在适当的时候重新加载下一页的数据
3.添加footerView
ListView 进行数据切换
思路 :创建两个适配器
AsyncTask 1.5 串行操作
AsyncTask 2. 并行操作
AsyncTask 4 串行(默认)+并行
回顾
getView(); 会被调用很多
每调用一次都需要创建一个条目布局(View对象)
优化ListView
1.listView的布局 宽和高 都是填充父窗体
2.复用convertView
convertView是getView方法的一个参数 convertView复用废弃view对象
使用convertView的好处是复用已经退出屏幕的view对象 而不是重新新的view对象
3.ViewHolder
ViewHolder的好处 减少findViewById的查找次数
使用的步骤
1.第一次加载的时候把查找的控件存到ViewHolder的对象中
2.把ViewHolder的对象放入convertView中
3.convertView取出ViewHolder的对象 ,然后从ViewHolder的对象中取出控件对象
当代码量比较多的时候 多去记忆过程(代码运行的流程和步骤)
第三个例子
package com.qf.day09_listview03;
public class MainActivity extends Activity {
List<Game> data;
MyAdapter adapter;
boolean flag = false;
int pageIndex = 1;
View footView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.
ListView listView = (ListView) findViewById(R.id.lv);
//2.
data = new ArrayList<>();
//3.
adapter = new MyAdapter(MainActivity.this,data);
footView = getLayoutInflater().inflate(R.layout.footer, null);
listView.addFooterView(footView);
//4.
listView.setAdapter(adapter);
//5.
new MyAsyncTask(MainActivity.this,data,adapter)
.execute("http://1000phone.net:8088/app/iAppFree/api/free.php?page="+pageIndex+"&number=20");
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(flag == true && scrollState == OnScrollListener.SCROLL_STATE_IDLE){
pageIndex = pageIndex + 1;
new MyAsyncTask(MainActivity.this,data,adapter)
.execute("http://1000phone.net:8088/app/iAppFree/api/free.php?page="+pageIndex+"&number=20");
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if( firstVisibleItem + visibleItemCount == totalItemCount ){
flag = true;
}else{
flag = false;
} }
});
}
}
package com.qf.day09_listview03;
public class MyAdapter extends BaseAdapter{
Context context;
List<Game> data;
Map<String,Bitmap> cacheImage = new HashMap<>();//用来存储已经浏览过的图片
public MyAdapter(Context context, List<Game> data) {
super();
this.context = context;
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
convertView = View.inflate(context, R.layout.item01, null);
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.item_iv);
holder.textView = (TextView) convertView.findViewById(R.id.item_tv);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
Game game = data.get(position);
holder.textView.setText(game.name);
holder.imageView.setTag(game.iconUrl);
if(cacheImage.containsKey(game.iconUrl)){//从缓存中读取图片
holder.imageView.setImageBitmap(cacheImage.get(game.iconUrl));
}else{//如果缓存中不存在该图片则访问网络获取图片
//设置一个预览图片
holder.imageView.setImageResource(R.drawable.logo);
new ImageAsyncTask(context, holder.imageView,position,game.iconUrl,cacheImage)
//.execute(game.iconUrl);
//子线程并行执行
.executeOnExecutor(Executors.newFixedThreadPool(1), game.iconUrl);
}
return convertView;
}
class ViewHolder{
ImageView imageView;
TextView textView;
}
//--------------------------------------------------------------------
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
package com.qf.day09_listview03;import java.util.List;
import android.content.Context;import android.os.AsyncTask;
import android.widget.Toast;
public class MyAsyncTask extends AsyncTask<String, Void, byte[]>{ Context context;
List<Game> data;
MyAdapter adapter;
public MyAsyncTask(Context context, List<Game> data, MyAdapter adapter) {
super();
this.context = context;
this.data = data;
this.adapter = adapter;
}
@Override
protected byte[] doInBackground(String... params) {
return HttpUtils.getData(params[0]); }
@Override
protected void onPostExecute(byte[] result) {
super.onPostExecute(result);
if(result != null){
String jsonString = new String(result);
List<Game> data2 = JsonUtils.parseJson(jsonString);
data.addAll(data2);
adapter.notifyDataSetChanged();
}else{
Toast.makeText(context, "网络异常", Toast.LENGTH_SHORT).show();
} } }
package com.qf.day09_listview03;
public class JsonUtils {
public static List<Game> parseJson(String jsonString) {
List<Game> data2 = new ArrayList<>();
try {
JSONObject obj1 = new JSONObject(jsonString);
JSONArray array = obj1.getJSONArray("applications");
Game game;
for(int i=0;i<array.length();i++){
JSONObject obj2 = array.getJSONObject(i);
game = new Game();
game.name = obj2.getString("name");
game.iconUrl = obj2.getString("iconUrl");
data2.add(game);
}
} catch (JSONException e) {
e.printStackTrace();
}
return data2;
}
}