📌  相关文章
📜  如何使用 Android RecyclerView 以表格形式显示数据?

📅  最后修改于: 2022-05-13 01:54:40.623000             🧑  作者: Mango

如何使用 Android RecyclerView 以表格形式显示数据?

RecyclerView 是作为 GridView 和 ListView 的继承者添加到 android studio 中的 ViewGroup。这是对两者的改进,可以在最新的 v-7 支持包中找到。它的创建是为了可以将任何具有 XML 布局的列表构建为可以大量定制的项目,同时提高 ListViews 和 GridViews 的效率。这种改进是通过回收用户不可见的视图来实现的。例如,如果用户向下滚动到项目 4 和 5 可见的位置;项目 1、2 和 3 将从内存中清除以减少内存消耗。不仅如此,Recycler View 还可以用于以表格的形式显示大量数据。就像电子表格一样,我们可以创建一个高度可定制的表格结构来填充其中的数据。在本文中,我们将了解如何构建这样的表格结构并从数据库中填充数据。在本例中,我们使用的是 Firebase 数据库,但您可以使用任何数据库。所以请按照以下步骤,让我们开始吧。

分步实施

第 1 步:创建一个新项目

要在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目。请注意,选择Java作为编程语言。

第 2 步:创建模型类

创建一个名为 Model 的新类,它将保存用户输入的各种数据。在这种情况下,我们存储字符串数据用户名和其他三个整数数据正确、尝试、时间。此数据代表测验竞赛结果。下面是实现正确模型类的代码。为了创建模型类,我们声明私有类变量并生成它们的 getter 和 setter 以及类的构造函数。

Java
public class Record {
 
    // Create private data variables
    private String attempted;
    private String correct;
    private String time;
    private String name;
 
    // generate getters and setters
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAttempted() {
        return attempted;
    }
 
    public void setAttempted(String attempted) {
        this.attempted = attempted;
    }
 
    public String getCorrect() {
        return correct;
    }
 
    public void setCorrect(String correct) {
        this.correct = correct;
    }
 
    public String getTime() {
        return time;
    }
 
    public void setTime(String time) {
        this.time = time;
    }
}


XML

 
      
    
 
          
        
 
 
          
        
 
          
        
 
          
        
 
    
 
      
    
 


XML


 
    
 
        
 
        
 
        
 
        
 
    
 


Java
mport android.view.View;
import android.widget.TextView;
 
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
 
 
public class MyViewHolder extends RecyclerView.ViewHolder {
 
    // data variables to link with
    // the respective id from the view
    TextView name, attempted, correct, time;
 
    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
 
        name = itemView.findViewById(R.id.userName);
        attempted = itemView.findViewById(R.id.attempted);
        correct = itemView.findViewById(R.id.correct);
        time = itemView.findViewById(R.id.time);
 
    }
}


Java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
 
// Extends the Adapter class to RecyclerView.Adapter
// and implement the unimplemented methods
public class RecordAdapter extends RecyclerView.Adapter {
 
    Context context;
    ArrayList list;
 
    // constructor with Record's data model list and view context
    public RecordAdapter(Context context, ArrayList list) {
        this.context = context;
        this.list = list;
    }
 
    // Binding data to the
    // into specified position
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // inflate the recycler view
        // layout in its view component
        View v = LayoutInflater.from(context).inflate(R.layout.record_info,parent,false);
        return  new MyViewHolder(v);
    }
 
    // holder method to set respective
    // data to their components
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Record user = list.get(position);
        holder.name.setText(user.getName());
        holder.attempted.setText(user.getAttempted());
        holder.correct.setText(user.getCorrect());
        holder.time.setText(user.getTime());
    }
 
    // method to return the
    // position of the item
    @Override
    public int getItemCount() {
        return list.size();
    }
 
}


Java
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.Objects;
 
public class RecordActivity extends AppCompatActivity {
 
    private ImageView back, profileImage;
 
    private DatabaseReference databaseReference;
 
    private RecyclerView recyclerView;
 
    private RecordAdapter myAdapter;
 
    // Using ArrayList to Record data
    private ArrayList list;
 
    private int flag = 0;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record);
        getRecord();
    }
 
    private void getRecord() {
 
        // Getting reference of recyclerView
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
       
        // Setting the layout as linear
        // layout for vertical orientation
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
 
        list = new ArrayList<>();
        myAdapter = new RecordAdapter(this,list);
       
        // Setting Adapter to RecyclerView
        recyclerView.setAdapter(myAdapter);
 
        // get firebase instance for the desired key location
        databaseReference = FirebaseDatabase.getInstance().getReference();
        databaseReference.child("User").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if(flag==0) {
                    for (DataSnapshot ds : snapshot.getChildren()) {
                        for (DataSnapshot dss : ds.getChildren()) {
                            if (Objects.equals(dss.getKey(), "Total")) {
                                // adding record data to the list
                                Record user = dss.getValue(Record.class);
                                list.add(user);
                            }
                        }
                    }
                    // notifying adapter class about the change
                    myAdapter.notifyDataSetChanged();
                    flag=1;
                }
                progressBar.dismiss();
            }
 
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
 
            }
        });
    }
 
    @Override
    public void onBackPressed() {
        startActivity(new Intent(getApplicationContext(), MainActivity.class));
        super.onBackPressed();
    }
}


第 3 步:使用 activity_main.xml 文件

XML 代码用于构建活动的结构及其样式部分。在这个 XML 文件中,我们将创建一个水平方向的 LinearLayout。这将包含四个 ImageView 表示 Record 类数据模型实体的各种数据列的图标。下面我们将创建一个RecyclerView来填充数据。下面是 activity_main.xml 文件的代码。

XML


 
      
    
 
          
        
 
 
          
        
 
          
        
 
          
        
 
    
 
      
    
 

第 4 步:创建 RecyclerView 项目布局

在下一步中,我们将创建一个项目布局,它将保存每个 RecyclerView 项目的数据。在这个布局中,会有四个不同 id 属性的 TextView 视图。

XML



 
    
 
        
 
        
 
        
 
        
 
    
 

第 5 步:使用 ViewHolder

在此,我们将为我们的数据模型类创建一个视图持有者。视图持有者用于描述元数据及其在回收站视图中的位置。在这里,我们将使用视图持有者来放置模型类变量的数据,这些变量是名称、尝试、正确、时间。下面是 ViewHolder 的代码。

Java

mport android.view.View;
import android.widget.TextView;
 
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
 
 
public class MyViewHolder extends RecyclerView.ViewHolder {
 
    // data variables to link with
    // the respective id from the view
    TextView name, attempted, correct, time;
 
    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
 
        name = itemView.findViewById(R.id.userName);
        attempted = itemView.findViewById(R.id.attempted);
        correct = itemView.findViewById(R.id.correct);
        time = itemView.findViewById(R.id.time);
 
    }
}

第 6 步:处理适配器类

适配器是负责 RecyclerView 的主要代码。它包含处理 RecyclerView 实现的所有重要方法。成功实施的基本方法是:

  • onCreateViewHolder:将卡片布局的膨胀处理为 RecyclerView 的一个项目。
  • onBindViewHolder:处理RecyclerView的特定item点击相关的不同数据和方法的设置。
  • getItemCount:返回 RecyclerView 的长度。
  • onAttachedToRecyclerView:将适配器附加到 RecyclerView。

Java

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
 
// Extends the Adapter class to RecyclerView.Adapter
// and implement the unimplemented methods
public class RecordAdapter extends RecyclerView.Adapter {
 
    Context context;
    ArrayList list;
 
    // constructor with Record's data model list and view context
    public RecordAdapter(Context context, ArrayList list) {
        this.context = context;
        this.list = list;
    }
 
    // Binding data to the
    // into specified position
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // inflate the recycler view
        // layout in its view component
        View v = LayoutInflater.from(context).inflate(R.layout.record_info,parent,false);
        return  new MyViewHolder(v);
    }
 
    // holder method to set respective
    // data to their components
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Record user = list.get(position);
        holder.name.setText(user.getName());
        holder.attempted.setText(user.getAttempted());
        holder.correct.setText(user.getCorrect());
        holder.time.setText(user.getTime());
    }
 
    // method to return the
    // position of the item
    @Override
    public int getItemCount() {
        return list.size();
    }
 
}

第 7 步:处理 RecordActivity 类

在这个类中,我们为 RecyclerView、Adapter Class、ViewHolder 创建实例。这里我们使用 Firebase 数据库来存储数据并对其进行请求调用,您可以使用任何其他数据库。

  • 创建适配器、视图持有者、回收者视图、数据库引用的对象。
  • 创建 Record 类的 Object 类型的 ArrayList。
  • 请求数据并将其存储在数组列表中。
  • 通知适配器列表中的更改。

Java

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.Objects;
 
public class RecordActivity extends AppCompatActivity {
 
    private ImageView back, profileImage;
 
    private DatabaseReference databaseReference;
 
    private RecyclerView recyclerView;
 
    private RecordAdapter myAdapter;
 
    // Using ArrayList to Record data
    private ArrayList list;
 
    private int flag = 0;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record);
        getRecord();
    }
 
    private void getRecord() {
 
        // Getting reference of recyclerView
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
       
        // Setting the layout as linear
        // layout for vertical orientation
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
 
        list = new ArrayList<>();
        myAdapter = new RecordAdapter(this,list);
       
        // Setting Adapter to RecyclerView
        recyclerView.setAdapter(myAdapter);
 
        // get firebase instance for the desired key location
        databaseReference = FirebaseDatabase.getInstance().getReference();
        databaseReference.child("User").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if(flag==0) {
                    for (DataSnapshot ds : snapshot.getChildren()) {
                        for (DataSnapshot dss : ds.getChildren()) {
                            if (Objects.equals(dss.getKey(), "Total")) {
                                // adding record data to the list
                                Record user = dss.getValue(Record.class);
                                list.add(user);
                            }
                        }
                    }
                    // notifying adapter class about the change
                    myAdapter.notifyDataSetChanged();
                    flag=1;
                }
                progressBar.dismiss();
            }
 
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
 
            }
        });
    }
 
    @Override
    public void onBackPressed() {
        startActivity(new Intent(getApplicationContext(), MainActivity.class));
        super.onBackPressed();
    }
}

输出:

要记住的事情:

  • 模型类应具有特定顺序的所需数据变量。
  • 视图持有者应膨胀回收器视图以填充数据。
  • 要对特定行进行 onClick 调用,请使用 onItemCount 方法。