【问题标题】:Convert ListView to RecyclerView将 ListView 转换为 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

标签: java android android-recyclerview android-listview


【解决方案1】:

我使用 RecyclerView.Adapter 重构了您的 ListView 适配器。

  1. onCreateView 为屏幕上的每个可见容器调用。如果你的屏幕可以显示 10 行数据 RecyclerView 制作 11 - 12 个容器(ViewHolder)
  2. onBindView 在您滚动时使用新数据更新这些容器。
  3. MyViewHolder 是保存每行数据的数据的对象(容器)
  4. static classbind() 在内部起作用以避免适配器中的任何内存泄漏。
  5. 我们可以使用itemViewparent 访问RecyclerView.Adapter 中的Context
  6. itemView 是每个容器 (ViewHolder) 的膨胀视图。
  7. 在 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());
        }

    }

}

您的活动:

  1. LinearLayoutManager 用于线性布局
  2. GridLayoutManager 用于网格布局
  3. 如果您确定 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

【讨论】:

    猜你喜欢
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2020-05-01
    • 1970-01-01
    • 2016-04-27
    相关资源
    最近更新 更多