本次要講的內容是利用RecyclerView顯示Users列表的信息,如下圖所示。 首先我們來創建模型User.java package com.example.mytest.User; import java.util.UUID; public class User{ private UUID m ...
本次要講的內容是利用RecyclerView顯示Users列表的信息,如下圖所示。
首先我們來創建模型User.java
package com.example.mytest.User;
import java.util.UUID;
public class User{
private UUID mId;
private String name;
public User() {
this(UUID.randomUUID());
}
public User(UUID id){
mId=id;
}
public UUID getId() {
return mId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"mId=" + mId +
", name='" + name + '\'' +
'}';
}
}
創建單例UserLab.java
user數組對象將存儲在一個單例里。單例是特殊的Java類,在創建實例時,一個單例類僅允許創建一個實例。
應用能在記憶體里存活多久,單例就能活多久。
package com.example.mytest.User;
import android.content.Context;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class UserLab {
private static UserLab sUserLab;
private List<User> mUsers;//保存User對象
//get()方法
public static UserLab get(Context context){
//如果實例存在直接返回它,如果不存在,調用構造方法創建它
if (sUserLab==null){
sUserLab=new UserLab(context);
}
return sUserLab;
}
//私有構造方法
private UserLab(Context context){
mUsers=new ArrayList<>();
//先批量存入100個User對象
for (int i=0;i<100;i++){
User user=new User();
user.setName("User #"+i);
mUsers.add(user);
}
}
public List<User> getUsers(){
return mUsers;
}
public User getUser(UUID id){
for (User user:mUsers){
if (user.getId().equals(id)){
return user;
}
}
return null;
}
}
創建通用型fragment托管佈局activity_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mytest.User.UserActivity">
</FrameLayout>
抽象activity類,創建SingleFragmentActivity.java
因為這段代碼很通用,所以抽取出來,便於簡化代碼。
package com.example.mytest.User;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import com.example.mytest.R;
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager fm=getSupportFragmentManager();
Fragment fragment=fm.findFragmentById(R.id.fragment_container);
if (fragment==null){
fragment=createFragment();
fm.beginTransaction().add(R.id.fragment_container,fragment).commit();
}
}
}
創建UserListActivity.java
繼承SingleFragmentActivity類,托管UserListFragment
package com.example.mytest.User;
import android.support.v4.app.Fragment;
public class UserListActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment() {
return new UserListFragment();
}
}
創建UserListFragment .java
public class UserListFragment extends Fragment {
}
在配置文件AndroidManifest.xml中聲明UserListActivity為launcher acticity
<activity android:name=".User.UserListActivity">
<!--添加這裡開始-->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!--添加這裡結束-->
</activity>
現在運行應用,會看到UserListActivity的FrameLayout托管了一個無內容的UserListFragment。
我們需要UserListFragment向用戶展示user列表,這就要用到RecyclerView類。RecyclerView是ViewGroup的子類,每一個列表項都是作為一個View子對象顯示的。
一次為所有列表項創建View很容易搞垮應用,按需創建視圖對象才是比較合理的解決方案。RecyclerView顧名思義就是回收再利用,用戶滑動屏幕切換視圖時,上一個視圖會回收利用,當然整個功能的實現還需要ViewHolder子類和Adapter子類的支持。
- RecyclerView的任務僅限於回收和定位屏幕上的View。
- ViewHolder只做一件事:容納View視圖。
- Adapter創建必要的ViewHolder,綁定ViewHolder至模型層數據。
現在我們來正式使用RecyclerView。
1. 添加RecyclerView依賴庫
dependencies {
...
compile 'com.android.support:recyclerview-v7:25.3.1'
}
2.新建fragment_user_list.xml佈局文件。
修改根視圖為RecyclerView,併為其配置ID
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/user_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</android.support.v7.widget.RecyclerView>
3.視圖和fragment關聯
修改UserListFragment類文件,使用佈局並找到佈局中的RecyclerView視圖。
註意,沒有LayoutManager的支持,不僅RecyclerView無法工作,還會導致應用崩潰。所以,RecyclerView視圖創建完成後,就立即轉交給了Manager對象。LayoutManager負責屏幕上列表項的擺放、定義屏幕滾動行為。
public class UserListFragment extends Fragment {
private RecyclerView mUserRecyclerView;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_user_list,container,false);
mUserRecyclerView=(RecyclerView)view.findViewById(R.id.user_recycler_view);
mUserRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return view;
}
}
4.實現ViewHolder和Adapter
public class UserListFragment extends Fragment {
........
//定義ViewHolder內部類,它會實例化並使用list_item_user佈局
private class UserHolder extends RecyclerView.ViewHolder{
private User mUser;
//構造方法
public UserHolder(LayoutInflater inflater,ViewGroup parent){
super(inflater.inflate(R.layout.list_item_user,parent,false));
}
}
//創建Adapter內部類
private class UserAdapter extends RecyclerView.Adapter<UserHolder>{
private List<User> mUsers;
public UserAdapter(List<User> users){
mUsers=users;
}
@Override
public UserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(getActivity());
return new UserHolder(layoutInflater,parent);
}
@Override
public void onBindViewHolder(UserHolder holder, int position) {
}
@Override
public int getItemCount() {
return mUsers.size();
}
}
}
新建updateUI方法。關聯Adapter和RecyclerView。
public class UserListFragment extends Fragment {
......
private UserAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_user_list,container,false);
mUserRecyclerView=(RecyclerView)view.findViewById(R.id.user_recycler_view);
mUserRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
private void updateUI() {
UserLab userLab=UserLab.get(getActivity());
List<User> users=userLab.getUsers();
mAdapter=new UserAdapter(users);
mUserRecyclerView.setAdapter(mAdapter);
}
......
}
運行應用,結果如圖所示。
現在綁定列表項,使呈現不同的數據。
我們把綁定工作放入UserHolder類里,綁定之前首先要實例化相關組件。由於是一次性任務,因此直接放在構造方法里處理。然後定義bind(User)方法,每次有新的User要在UserHolder中顯示時,都要調用它一次。
為了錦上添花,這裡還設置了列表項點擊後彈出小的提示框。通過實現View.OnClickListener介面來實現這個功能。
//定義ViewHolder內部類,它會實例化並使用list_item_user佈局
private class UserHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView mNameTextView;
private User mUser;
//構造方法
public UserHolder(LayoutInflater inflater,ViewGroup parent){
super(inflater.inflate(R.layout.list_item_user,parent,false));
//檢測用戶點擊事件
itemView.setOnClickListener(this);//點擊了則調用onClick()方法
//實例化視圖組件
mNameTextView=(TextView) itemView.findViewById(R.id.user_name);
}
//每次有新的User要在UserHolder中顯示時,都要調用它一次
public void bind(User user){
mUser=user;
mNameTextView.setText(mUser.getName());
}
@Override
public void onClick(View v) {
Toast.makeText(getActivity(),mUser.getName()+" clicked!",Toast.LENGTH_SHORT).show();
}
}
//創建Adapter內部類
private class UserAdapter extends RecyclerView.Adapter<UserHolder>{
.........
@Override
public void onBindViewHolder(UserHolder holder, int position) {
User user=mUsers.get(position);
holder.bind(user);
}
........
}
這裡為了方便大家的閱讀,再次提供UserListFragment.java的全部代碼。
package com.example.mytest.User;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.example.mytest.R;
import java.util.List;
public class UserListFragment extends Fragment {
private RecyclerView mUserRecyclerView;
private UserAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_user_list,container,false);
mUserRecyclerView=(RecyclerView)view.findViewById(R.id.user_recycler_view);
mUserRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
private void updateUI() {
UserLab userLab=UserLab.get(getActivity());
List<User> users=userLab.getUsers();
mAdapter=new UserAdapter(users);
mUserRecyclerView.setAdapter(mAdapter);
}
//定義ViewHolder內部類,它會實例化並使用list_item_user佈局
private class UserHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView mNameTextView;
private User mUser;
//構造方法
public UserHolder(LayoutInflater inflater,ViewGroup parent){
super(inflater.inflate(R.layout.list_item_user,parent,false));
//檢測用戶點擊事件
itemView.setOnClickListener(this);//點擊了則調用onClick()方法
//實例化視圖組件
mNameTextView=(TextView) itemView.findViewById(R.id.user_name);
}
//每次有新的User要在UserHolder中顯示時,都要調用它一次
public void bind(User user){
/* mUser=user;
mNameTextView.setText(mUser.getName());*/
}
@Override
public void onClick(View v) {
Toast.makeText(getActivity(),mUser.getName()+" clicked!",Toast.LENGTH_SHORT).show();
}
}
//創建Adapter內部類
private class UserAdapter extends RecyclerView.Adapter<UserHolder>{
private List<User> mUsers;
public UserAdapter(List<User> users){
mUsers=users;
}
@Override
public UserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(getActivity());
return new UserHolder(layoutInflater,parent);
}
@Override
public void onBindViewHolder(UserHolder holder, int position) {
User user=mUsers.get(position);
holder.bind(user);
}
@Override
public int getItemCount() {
return mUsers.size();
}
}
}
現在再次運行程式,效果如下圖。