将 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 classbind() 在内部起作用以避免适配器中的任何内存泄漏。 我们可以使用itemViewparent 访问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

如何将 lodash 对象(过滤器对象)动态转换为 jquery listview

如何迭代 ListView 项目以转换为卡片

如何绑定listView中项的子属性?