将 ListView 转换为 RecyclerView
Posted
技术标签:
【中文标题】将 ListView 转换为 RecyclerView【英文标题】:Convert ListView to RecyclerView 【发布时间】:2020-09-11 01:59:20 【问题描述】:我的应用中有一个列表视图。 我想将其更改为回收站视图,但即使使用不同的教程我也不明白。
我正在使用这个:https://www.spreys.com/listview-to-recyclerview/ 我在这里的“getView”部分失败了。
这是我的 ListActivity 和 LeagueArrayAdapter 的代码。
感谢您的帮助。
列表活动:
public class ListActivity extends AppCompatActivity implements AdapterView.OnItemClickListener
private ArrayAdapter adapter;
private final int REQUEST_CODE_EDIT = 1;
private static LeagueDAO leagueDAO;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
leagueDAO = MainActivity.getLeagueDAO();
List<League> allLeagues1 = leagueDAO.getLeagues();
if (allLeagues1.size() == 0)
leagueDAO.insert(new League("HVM Landesliga 19/20","https://hvmittelrhein-handball.liga.nu/cgi-bin/WebObjects/nuLigaHBDE.woa/wa/groupPage?championship=MR+19%2F20&group=247189"));
allLeagues1 = leagueDAO.getLeagues();
adapter = new LeagueArrayAdapter(this, R.layout.league, allLeagues1);
ListView lv = findViewById(R.id.league_list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
registerForContextMenu(lv);
Button btn_league_add = findViewById(R.id.btn_league_add);
btn_league_add.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Intent intent = new Intent(ListActivity.this, EditActivity.class);
startActivity(intent);
);
@Override
public void onCreateContextMenu(ContextMenu contMenu, View v,
ContextMenu.ContextMenuInfo contextmenuInfo)
super.onCreateContextMenu(contMenu, v, contextmenuInfo);
getMenuInflater().inflate(R.menu.team_list_context_menu, contMenu);
@Override
public boolean onContextItemSelected(MenuItem item)
AdapterView.AdapterContextMenuInfo acmi=
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
League league = (League)adapter.getItem(acmi.position);
switch (item.getItemId())
case R.id.evliconit_edit:
editEntry(league, acmi.position);
return true;
case R.id.evliconit_del:
leagueDAO.delete(league);
adapter.remove(league);
adapter.notifyDataSetChanged();
return true;
default:
return super.onContextItemSelected(item);
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
League team = (League)adapter.getItem(position);
editEntry(team, position);
private void editEntry(League league, int position)
Intent intent = new Intent(this, EditActivity.class);
intent.putExtra("team", league);
intent.putExtra("position", position);
startActivityForResult(intent, REQUEST_CODE_EDIT);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == REQUEST_CODE_EDIT && resultCode == RESULT_OK && intent != null)
Bundle extras = intent.getExtras();
int position = extras.getInt("position");
League league = (League) adapter.getItem(position);
league.setLeague_name(extras.getString("league_name"));
league.setLeague_url(extras.getString("league_url"));
adapter.notifyDataSetChanged();
@Override
protected void onRestart()
super.onRestart();
leagueDAO = MainActivity.getLeagueDAO();
List<League> allLeagues1 = leagueDAO.getLeagues();
adapter = new LeagueArrayAdapter(this, R.layout.league, allLeagues1);
ListView lv = findViewById(R.id.league_list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
registerForContextMenu(lv);
LeagueArrayAdapter:
public class LeagueArrayAdapter extends ArrayAdapter<League>
private List<League> leagues;
private Context context;
private int layout;
public LeagueArrayAdapter(Context context, int layout, List<League> leagues)
super(context, layout, leagues);
this.context = context;
this.layout = layout;
this.leagues = leagues;
@Override
public View getView(int position, View convertView, ViewGroup parent)
League league = leagues.get(position);
if (convertView == null)
convertView = LayoutInflater.from(context).inflate(layout, null);
TextView tv_name = convertView.findViewById(R.id.tv_name);
TextView tv_url = convertView.findViewById(R.id.tv_url);
tv_name.setText(league.getLeague_name());
tv_url.setText(league.getLeague_url());
return convertView;
更新:打开活动时应用崩溃
public class ListActivity extends AppCompatActivity implements AdapterView.OnItemClickListener
private ArrayAdapter adapter;
private final int REQUEST_CODE_EDIT = 1;
private static LeagueDAO leagueDAO;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
leagueDAO = MainActivity.getLeagueDAO();
List<League> allLeagues1 = leagueDAO.getLeagues();
if (allLeagues1.size() == 0)
leagueDAO.insert(new League("HVM Landesliga 19/20","https://hvmittelrhein-handball.liga.nu/cgi-bin/WebObjects/nuLigaHBDE.woa/wa/groupPage?championship=MR+19%2F20&group=247189"));
allLeagues1 = leagueDAO.getLeagues();
// adapter = new LeagueArrayAdapter(this, R.layout.league, allLeagues1);
RecyclerView lv = findViewById(R.id.league_list);
lv.setHasFixedSize(true);
lv.setLayoutManager(new LinearLayoutManager(this));
lv.setAdapter(new LeagueArrayAdapter(allLeagues1));
// lv.setOnItemClickListener(this);
registerForContextMenu(lv);
Button btn_league_add = findViewById(R.id.btn_league_add);
btn_league_add.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Intent intent = new Intent(ListActivity.this, EditActivity.class);
startActivity(intent);
);
【问题讨论】:
有什么问题? 你必须扩展 RecyclerView.Adapter 而不是 ArrayAdapter 【参考方案1】:我使用 RecyclerView.Adapter 重构了您的 ListView 适配器。
onCreateView
为屏幕上的每个可见容器调用。如果你的屏幕可以显示 10 行数据 RecyclerView 制作 11 - 12 个容器(ViewHolder)
onBindView
在您滚动时使用新数据更新这些容器。
MyViewHolder
是保存每行数据的数据的对象(容器)
static class
和 bind()
在内部起作用以避免适配器中的任何内存泄漏。
我们可以使用itemView
和parent
访问RecyclerView.Adapter
中的Context
itemView
是每个容器 (ViewHolder) 的膨胀视图。
在 ViewHolder 的构造函数中初始化您的视图,以便它们被分配一次。
public class LeagueArrayAdapter extends RecyclerView.Adapter<LeagueArrayAdapter.MyViewHolder>
private ArrayList<League> leagues;
public LeagueArrayAdapter(ArrayList<League> leagues)
this.leagues = leagues;
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
return LayoutInflater.from(parent.getContext()).inflate(R.layout.row_league, parent, false);
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position)
holder.bind(leagues.get(position));
@Override
public int getItemCount()
return 0;
static class MyViewHolder extends RecyclerView.ViewHolder
TextView tv_name;
TextView tv_url;
public MyViewHolder(@NonNull View itemView)
super(itemView);
tv_name = itemView.findViewById(R.id.tv_name);
tv_url = itemView.findViewById(R.id.tv_url);
void bind(League league)
tv_name.setText(league.getLeague_name());
tv_url.setText(league.getLeague_url());
您的活动:
LinearLayoutManager
用于线性布局
GridLayoutManager
用于网格布局
如果您确定 RecyclerView 本身不会改变宽度或高度,setHasFixedSize()
会提高 RecyclerView 的速度。
public class LeagueActivity extends AppCompatActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.YOUR_ACTIVITY_LAYOUT_ID);
...
RecyclerView recyclerView = findViewById(R.id.YOUR_RECYCLER_VIEW_ID);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new LeagueArrayAdapter(SEND_YOUR_ARRAY_OF_LEAGUE));
【讨论】:
感谢您的帮助,在 RecyclerView.Adapter 之后我必须更改 ListActivity 但我不明白 @Philip 查看更新后的答案,希望对您有所帮助。 谢谢!更新我的帖子,打开活动时应用程序崩溃。【参考方案2】:我建议检查 Groupie Lbrary,它与 recyclerView 一起使用,它让你的生活更轻松,这是一个如何使用它的示例(我正在用 kotlin 编写代码,但不应该这样不同于java)
首先,将这些行添加到您的 Build.gradle (app) 文件中
implementation 'com.xwray:groupie:2.3.0'
implementation 'com.xwray:groupie-kotlin-android-extensions:2.3.0'
然后在您的活动中创建一个适配器,然后将适配器设置为您的 recyclerView
val myAdapter = GroupAdapter<ViewHolder>()
recyclerView.adapter = myAdapter
就像这样,您将适配器设置为您的 recyclerView,但您必须创建“项目”以放入 recyclerView。你可以像这样创建一个项目
class MyItem: Item()
override fun getLayout() = R.layout.layout_seen
override fun bind(viewHolder: ViewHolder, position: Int)
在 getLayout 方法中,您返回要在 recyclerView 中显示的布局, 您可以使用 bind 方法对我们正在显示的布局进行任何类型的修改。
最后,我们可以通过这种方式将我们的项目添加到适配器中
myAdapter.add(MyItem())
myAdapter.notifyDataSetChanged()
有关更多详细信息,请查看库,在这里我只是解释了如何简单地将项目添加到 RecyclerView
【讨论】:
以上是关于将 ListView 转换为 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章
Json 到 ListView - 无法将类型转换为 IEnumerable - Xamarin
带有子项的 Android ListView 导致无法将 TwoLineListItem 强制转换为 android.widget.TextView
如何在 Kotlin 中将 listView 转换为 RecyclerView