ListView高效刷新——刷新单条数据
来源:互联网 发布:js获取class为a的div 编辑:程序博客网 时间:2024/05/17 22:23
对于ListView数据的刷新大家都知道,改变Adapter的数据源,然后调用Adapter的notifyDateSetChanged()方法即可。
用的listview展示所有正在下载的内容。因为下载进度要实时更新,所以要不停的调用notifyDateSetChanged刷新数据。这样会不停的重新绘制整个listview的界面,性能开销非常大。而且如果每个item有图片的话,每个item的图片都需要重新加载,就算图片做了内存缓存,刷新一下图片也会闪一下,不停的刷新就会导致各个item的图片不停的闪,体验一点都不好。那么对于上面问题,有没有解决办法呢?当然是有的。我们可以针对某一个item进行局部更新,而不影响其它没有修改的item。那么具体如何实现的呢?
getView方法被多次调用(画面上能显示多少就会被调用多少次),并且在有获取网络图片的情况下会可能造成大量闪动或卡顿,极大的影响用户体验。
一些方法的介绍:
ListView.getFirstVisiblePosition():获取第一个可见的item
ListView.getLastVisiblePosition():获取最后一个可见的item
ListView.getItemAtPosition(position):获取item数据集
Adapter.getItem(position):获取item数据集,等同上面方法
ListView.getChildAt(position):获取到的是当前可见的第position项的itemview,获取的时候还需要做一个位置计算。
Adapter.getView(position, itemView , ListView ):刷新单个itemview界面
adapter.notifyDataSetChanged():是对listview的所有可见item(最上面和最下面半个也算)进行刷新,初始化listview或者手动调用此方法时都会调用getView且次数为item的可见个数。
listView.getAdapter():获取listview的adapter
实现原理:
(1)找到需要更新的item在adapter中的位置;
(2)更新adapter中item的数据data;
(3)如果该item在listView当前屏的可见范围内,则更新内容,否则不需要更新,待下次adapter刷新全部时再刷新;
更新方式:
方式1、获取itemview里的控件直接设置
View view = mListView.getChildAt(targetIndex - startShownIndex);TextView textView = (TextView) view.findViewById(R.id.textView);textView.setText(datas.get(targetIndex));
方式2、获取itemview然后调用getview方法
View view = mListView.getChildAt(targetIndex - startShownIndex); myAdapter.getView(targetIndex, view, mListView);//核心方法
方式3、直接更新listview的所有item
myAdapter.notifyDataSetChanged();//核心方法
demo如下:
package com.example.draggridview;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.AdapterView;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * Created by Administrator on 2017/6/19. */public class MyActivity extends AppCompatActivity { private ListView mListView; private List<String> datas; private MyAdapter myAdapter; private Button btn,btn1, btn2; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); datas = new ArrayList<>(); for (int i = 0; i < 20; i++) { datas.add(i + ""); } mListView = (ListView) findViewById(R.id.listview); btn1 = (Button) findViewById(R.id.btn1); btn2 = (Button) findViewById(R.id.btn2); btn = (Button) findViewById(R.id.btn); myAdapter = new MyAdapter(MyActivity.this, datas); mListView.setAdapter(myAdapter); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //1、找到item内容为5的position String targetString = "5"; int targetIndex = -1; for (int j = 0; j < mListView.getCount(); j++) { //通过listView获取item的数据集,等同于baseAdapter的getItem方法 String itemString = mListView.getItemAtPosition(j).toString(); if (targetString.equals(itemString)) { targetIndex = j; break; } } if (targetIndex >= 0) { //2、改变它的数据集 datas.set(targetIndex, "改变!!!!"); //3、可见时调用setText刷新界面 int startShownIndex = mListView.getFirstVisiblePosition(); int endShownIndex = mListView.getLastVisiblePosition(); if (targetIndex >= startShownIndex && targetIndex <= endShownIndex) { View view = mListView.getChildAt(targetIndex - startShownIndex); TextView textView = (TextView) view.findViewById(R.id.textView); textView.setText(datas.get(targetIndex)); } } } }); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //1、找到item内容为8的position String targetString = "8"; int targetIndex = -1; for (int j = 0; j < mListView.getCount(); j++) { //通过listView获取item的数据集,等同于baseAdapter的getItem方法 String itemString = mListView.getItemAtPosition(j).toString(); if (targetString.equals(itemString)) { targetIndex = j; break; } } if (targetIndex >= 0) { //2、改变它的数据集 datas.set(targetIndex, "改变!!!!"); //3、可见时调用getView刷新界面 int startShownIndex = mListView.getFirstVisiblePosition(); int endShownIndex = mListView.getLastVisiblePosition(); if (targetIndex >= startShownIndex && targetIndex <= endShownIndex) { View view = mListView.getChildAt(targetIndex - startShownIndex);// mListView.getAdapter().getView(targetIndex, view, mListView); myAdapter.getView(targetIndex, view, mListView);//核心方法 } } } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //1、找到item内容为2的position String targetString = "2"; int targetIndex = -1; for (int j = 0; j < mListView.getCount(); j++) { //通过listView获取item的数据集,等同于baseAdapter的getItem方法 String itemString = mListView.getItemAtPosition(j).toString(); if (targetString.equals(itemString)) { targetIndex = j; break; } } if (targetIndex >= 0) { //2、改变它的数据集 datas.set(targetIndex, "改变!!!!"); //3、可见时调用getView刷新界面 int startShownIndex = mListView.getFirstVisiblePosition(); int endShownIndex = mListView.getLastVisiblePosition(); if (targetIndex >= startShownIndex && targetIndex <= endShownIndex) { myAdapter.notifyDataSetChanged();//核心方法 } } } }); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { //参数:listview,listview的item布局,位置,ID @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //数据集的变化 datas.set(position, "这是被更新的数据哦"); //滚动看不见之后再次可见时会显示这条数据 if (position != datas.size() - 1) { datas.set(position + 1, "这是被更新的数据哦,但是不展示"); } //方法一 //通过listview的item拿到TextView来更新控件数据 //TextView testView = (TextView) view.findViewById(R.id.textView); //testView.setText(datas.get(position)); //方法二 //通过调用getview来更新整个item myAdapter.getView(position, view, mListView); //方法三 //通过调用notifyDataSetChanged来更新整个listView //myAdapter.notifyDataSetChanged(); //ID和position一样的值 Log.e("MainActivity", "position==" + position); Log.e("MainActivity", "id==" + id); //ListView.getItemAtPosition(position)等价于Adapter.getItem(position) Log.e("MainActivity", "getItemAtPosition==" + mListView.getItemAtPosition(position).toString()); } }); }}
activity_my.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MyActivity"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="setText改变字符串为5的item!!!" android:textSize="25sp" /> <Button android:id="@+id/btn1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="getView改变字符串为8的item!!!" android:textSize="25sp" /> <Button android:id="@+id/btn2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="notifyDataSetChanged改变字符串为2的item!!!" android:textSize="25sp" /> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /></LinearLayout>
MyAdapter.java
package com.example.draggridview;import android.content.Context;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import java.util.List;/** * Created by Administrator on 2017/6/19. */public class MyAdapter extends BaseAdapter { private Context mContext; private List<String> datas; public MyAdapter(Context context, List<String> datas) { this.mContext = context; this.datas = datas; } @Override public int getCount() { return datas == null ? 0 : datas.size(); } @Override public Object getItem(int position) { return datas.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) { convertView = LayoutInflater.from(mContext).inflate(R.layout.item_adapter, null); viewHolder = new ViewHolder(); viewHolder.mTextView = (TextView) convertView.findViewById(R.id.textView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.mTextView.setText(datas.get(position)); Log.e("MainActivity", "getView position==" + position); return convertView; } class ViewHolder { private TextView mTextView; }}
item_adapter.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="vertical"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="60dp" android:gravity="center" android:textSize="45sp" android:text="1" /></LinearLayout>
测试结果:
1、直接设置setText:不会调用getView方法
2、获取itemview然后调用adapter.getview方法:只调用一次当前position的getview方法。
3、notifyDataSetChanged:会调用所有可见item的getview方法
参考:
ListView高效刷新——刷新单条数据
Android RecyclerView与ListView局部刷新
ListView实现Item局部刷新
面试 – ListView对其指定的子Item进行单独的刷新
listview局部刷新
ListView中单独更新某个Item的方法
- ListView高效刷新——刷新单条数据
- ListView高效刷新——刷新单条数据
- ListView 单条item刷新
- Android ListView 实现单条刷新
- ListView单条刷新的方法
- IOS UITableView单条刷新,数据不刷新解决方案
- listivew单条刷新
- android ListView 单条刷新方法实践及原理解析
- android ListView 单条刷新方法实践及原理解析
- 【android】ListView 单条刷新方法实践及原理解析
- Android ListView 单条刷新方法实践及原理解析
- Android ListView 单条刷新方法实践及原理解析
- android ListView 单条刷新方法实践及原理解析
- android ListView 单条刷新方法实践及原理解析
- ListView刷新数据方法
- Android ListView数据刷新
- ListView数据动态刷新
- Qt ListView 刷新数据
- 多线程与并发小Demo
- CodeForces
- 数据结构——树的基本运算
- CC2630 TIMAC协议栈低功耗问题
- CXXXView中增加数组(画线、画笔、画刷、位图、透明画刷、连续画图同理)
- ListView高效刷新——刷新单条数据
- Android 沉浸式状态栏解决方案
- Java开发--JDK安装笔记
- mini
- HDU 2859 Phalanx (DP)
- 网络---CRC校验
- ENVI栅格裸数据生成shp和kml矢量文件
- PCI开发备忘录
- 文件权限