Android持久化ListView回收
Android Persistent ListView recycling
几天来我一直在和这个问题作斗争。在 Whosebug 或任何提供解决方案的地方寻找解决方案,尝试了所有这些甚至尝试过 recyclerView 但没有任何帮助。
我的问题是我在 listItem 上有一个 listview 和两个 textView。因此,每当我单击列表项时,一个 textView 的可见性就会消失。但是当我向下滚动时,我看到不仅点击的一个消失了,而且许多其他的也消失了。
这是我的代码
CustomAdapter.java class
package com.example.nara.testtt;
import android.content.Context;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.
import java.util.ArrayList;
public class CustomAdapter extends BaseAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
public CustomAdapter(Context context){
this.context = context;
for(int i = 0; i < 50; i++){
list.add("item at " + i);
}
}
@Override
public int getCount() {
return list.size();
}
@Override
public String getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView == null){
LayoutInflater inflator = LayoutInflater.from(context);
convertView = inflator.inflate(R.layout.list_item,null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else{
holder = (ViewHolder)convertView.getTag();
}
holder.tv1.setText(getItem(position));
holder.tv2.setText(getItem(position));
return convertView;
}
public static class ViewHolder{
private TextView tv1;
private TextView tv2;
public ViewHolder(View view){
tv1 = (TextView) view.findViewById(R.id.textView);
tv2 = (TextView) view.findViewById(R.id.textView2);
}
}
}
MainActivity.java
package com.example.nara.testtt;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
CustomAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new CustomAdapter(this);
ListView lv = (ListView) findViewById(R.id.listView);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view.findViewById(R.id.textView);
tv.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
在 getView()
中,在设置文本后将文本视图的可见性更新为可见,因为 ListView 中的列表项将被回收。
holder.tv1.setText(getItem(position));
holder.tv2.setText(getItem(position));
holder.tv1.setVisibility(View.VISIBLE);
//Your code.....
更新:
public class CustomAdapter 扩展 BaseAdapter {
私有 ArrayList 列表 = new ArrayList();
私有上下文上下文;
public CustomAdapter(Context context) {
this.context = context;
for (int i = 0; i < 50; i++) {
list.add(new Bean("item at " + i));
}
}
@Override
public Bean getItem(int position) {
return list.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Initialization .......
Bean item = getItem(position);
holder.tv1.setText(item.name);
holder.tv2.setText(item.name);
holder.tv1.setVisibility(item.visibility);
return convertView;
}
// ViewHolder declaration
.......
public static class Bean {
String name;
int visibility = View.VISIBLE;
public Bean(String name) {
this.name = name;
}
}
在您的 activity 上的 onItemClick 中。
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view.findViewById(R.id.textView);
Bean bean = Adapter.getItem(position);
bean.visibility = View.GONE
tv.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
}
问题是视图在您的适配器中被回收。因此,当您滚动时,旧视图将用于新视图。这意味着如果旧视图的项目的可见性设置为 GONE
,在新视图中仍然是 GONE
。如果您不想保存可见性,您可以将它们设置为在您的适配器中可见:
holder.tv1.setVisibility(View.VISIBLE);
holder.tv1.setText(getItem(position));
holder.tv2.setText(getItem(position));
或者您将布尔值存储在列表或类似的东西中,然后询问是否单击了该项目:
if(clicked.get(i)) holder.tv1.setVisibility(View.GONE);
else holder.tv1.setVisibility(View.VISIBLE);
替换
convertView = inflator.inflate(R.layout.list_item,null);
和
convertView = inflator.inflate(R.layout.list_item,container,false);
几天来我一直在和这个问题作斗争。在 Whosebug 或任何提供解决方案的地方寻找解决方案,尝试了所有这些甚至尝试过 recyclerView 但没有任何帮助。
我的问题是我在 listItem 上有一个 listview 和两个 textView。因此,每当我单击列表项时,一个 textView 的可见性就会消失。但是当我向下滚动时,我看到不仅点击的一个消失了,而且许多其他的也消失了。 这是我的代码
CustomAdapter.java class
package com.example.nara.testtt;
import android.content.Context;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.
import java.util.ArrayList;
public class CustomAdapter extends BaseAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
public CustomAdapter(Context context){
this.context = context;
for(int i = 0; i < 50; i++){
list.add("item at " + i);
}
}
@Override
public int getCount() {
return list.size();
}
@Override
public String getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView == null){
LayoutInflater inflator = LayoutInflater.from(context);
convertView = inflator.inflate(R.layout.list_item,null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else{
holder = (ViewHolder)convertView.getTag();
}
holder.tv1.setText(getItem(position));
holder.tv2.setText(getItem(position));
return convertView;
}
public static class ViewHolder{
private TextView tv1;
private TextView tv2;
public ViewHolder(View view){
tv1 = (TextView) view.findViewById(R.id.textView);
tv2 = (TextView) view.findViewById(R.id.textView2);
}
}
}
MainActivity.java
package com.example.nara.testtt;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
CustomAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new CustomAdapter(this);
ListView lv = (ListView) findViewById(R.id.listView);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view.findViewById(R.id.textView);
tv.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
在 getView()
中,在设置文本后将文本视图的可见性更新为可见,因为 ListView 中的列表项将被回收。
holder.tv1.setText(getItem(position));
holder.tv2.setText(getItem(position));
holder.tv1.setVisibility(View.VISIBLE);
//Your code.....
更新:
public class CustomAdapter 扩展 BaseAdapter { 私有 ArrayList 列表 = new ArrayList(); 私有上下文上下文;
public CustomAdapter(Context context) {
this.context = context;
for (int i = 0; i < 50; i++) {
list.add(new Bean("item at " + i));
}
}
@Override
public Bean getItem(int position) {
return list.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Initialization .......
Bean item = getItem(position);
holder.tv1.setText(item.name);
holder.tv2.setText(item.name);
holder.tv1.setVisibility(item.visibility);
return convertView;
}
// ViewHolder declaration
.......
public static class Bean {
String name;
int visibility = View.VISIBLE;
public Bean(String name) {
this.name = name;
}
}
在您的 activity 上的 onItemClick 中。
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view.findViewById(R.id.textView);
Bean bean = Adapter.getItem(position);
bean.visibility = View.GONE
tv.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
}
问题是视图在您的适配器中被回收。因此,当您滚动时,旧视图将用于新视图。这意味着如果旧视图的项目的可见性设置为 GONE
,在新视图中仍然是 GONE
。如果您不想保存可见性,您可以将它们设置为在您的适配器中可见:
holder.tv1.setVisibility(View.VISIBLE);
holder.tv1.setText(getItem(position));
holder.tv2.setText(getItem(position));
或者您将布尔值存储在列表或类似的东西中,然后询问是否单击了该项目:
if(clicked.get(i)) holder.tv1.setVisibility(View.GONE);
else holder.tv1.setVisibility(View.VISIBLE);
替换
convertView = inflator.inflate(R.layout.list_item,null);
和
convertView = inflator.inflate(R.layout.list_item,container,false);