java - Fragment 内的 RecyclerView 未正确显示

标签 java android firebase android-fragments android-recyclerview

我目前正在开发一个类似 WhatsApp 的 Android 应用程序,最近遇到了一个让我头疼的问题。我正在尝试在属于 TabLayout 的 Fragment 内创建 RecyclerView。基本上,我有 3 个选项卡,每个选项卡都包含一个 Fragment。第一个选项卡用于用户的对话,第二个选项卡用于组,第三个选项卡用于联系人。每个选项卡都应包含一个 RecyclerView,它根据 Firebase 身份验证提供的当前用户 ID 显示来自 Firebase Firestore 的数据。我认为问题在于,除了 RecyclerView 之外,Fragment 内部还有一个 FloatingActionButton。此按钮在每个 fragment 中用于执行发送新消息或创建新组或添加新联系人等操作。单击时,假设在组选项卡内,FAB 将显示一个 AlertDialog,要求用户填写组名称,然后选择“创建”,然后将创建该组并将其添加到数据库中。现在的问题是,当用户登录应用程序并访问“组”选项卡时,不会显示其组,但如果用户单击 FAB,则会出现 AlertDialog,并且如果用户单击 EditText 以选择名称对于新组,用户的组突然显示在 fragment 内。我需要一些帮助,我对 Android 没有太多经验,我认为我搞乱了布局,但我自己无法真正弄清楚。

这是我的代码:

MainActivity.java

    package com.example.snakemessenger;

    import android.content.Intent;
    import android.os.Bundle;

    import androidx.annotation.NonNull;

    import android.view.MenuItem;
    import com.google.android.material.tabs.TabLayout;
    import com.google.firebase.auth.FirebaseAuth;
    import com.google.firebase.auth.FirebaseUser;
    import com.google.firebase.firestore.FirebaseFirestore;
    import com.google.firebase.storage.FirebaseStorage;
    import com.google.firebase.storage.StorageReference;

    import androidx.appcompat.app.AppCompatActivity;
    import androidx.appcompat.widget.Toolbar;
    import androidx.viewpager.widget.ViewPager;

    import android.view.Menu;
    import android.widget.Toast;

    public class MainActivity extends AppCompatActivity {
        public static final String TAG = "SnakeMessenger";
        private FirebaseAuth mAuth;
        private FirebaseFirestore db;
        private StorageReference storageReference;

        private ViewPager mViewPager;
        private TabLayout mTabLayout;
        private TabsAccessorAdapter mTabsAccessorAdapter;

        private FirebaseUser currentUser;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar mToolbar = findViewById(R.id.main_page_toolbar);
            setSupportActionBar(mToolbar);
            getSupportActionBar().setTitle("Snake Messenger");

            mAuth = FirebaseAuth.getInstance();
            db = FirebaseFirestore.getInstance();
            storageReference = FirebaseStorage.getInstance().getReference();

            currentUser = mAuth.getCurrentUser();

            if (currentUser == null) {
                sendUserToLoginActivity();
            }

            mViewPager = findViewById(R.id.main_tabs_pager);
            mTabsAccessorAdapter = new TabsAccessorAdapter(getSupportFragmentManager());
            mViewPager.setAdapter(mTabsAccessorAdapter);

            mTabLayout = findViewById(R.id.main_tabs);
            mTabLayout.setupWithViewPager(mViewPager);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);

            getMenuInflater().inflate(R.menu.options_menu, menu);

            return true;
        }

        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
            super.onOptionsItemSelected(item);

            if (item.getItemId() == R.id.main_find_friends_option) {
                // TODO
            } else if (item.getItemId() == R.id.main_settings_option) {
                sendUserToSettingsActivity();
            } else if (item.getItemId() == R.id.main_sign_out_option) {
                mAuth.signOut();
                sendUserToLoginActivity();
                Toast.makeText(MainActivity.this, "Signed out", Toast.LENGTH_SHORT).show();
            }

            return true;
        }

        private void sendUserToSettingsActivity() {
            Intent settingsIntent = new Intent(MainActivity.this, SettingsActivity.class);
            startActivity(settingsIntent);
        }

        private void sendUserToLoginActivity() {
            Intent loginIntent = new Intent(MainActivity.this, SignInActivity.class);
            loginIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(loginIntent);
            finish();
        }
    }

TabsAccessorAdapter.java


    package com.example.snakemessenger;

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.fragment.app.FragmentPagerAdapter;

    public class TabsAccessorAdapter extends FragmentPagerAdapter {
        public TabsAccessorAdapter(@NonNull FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new ChatsFragment();
                case 1:
                    return new GroupsFragment();
                case 2:
                    return new FriendsFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return 3;
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "Chats";
                case 1:
                    return "Groups";
                case 2:
                    return "Friends";
                default:
                    return null;
            }
        }
    }

GroupsFragment.java


    package com.example.snakemessenger;

    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.Toast;

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AlertDialog;
    import androidx.fragment.app.Fragment;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;

    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.OnFailureListener;
    import com.google.android.gms.tasks.OnSuccessListener;
    import com.google.android.gms.tasks.Task;
    import com.google.android.material.floatingactionbutton.FloatingActionButton;
    import com.google.firebase.auth.FirebaseAuth;
    import com.google.firebase.auth.FirebaseUser;
    import com.google.firebase.firestore.FirebaseFirestore;
    import com.google.firebase.firestore.QueryDocumentSnapshot;
    import com.google.firebase.firestore.QuerySnapshot;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import de.hdodenhof.circleimageview.CircleImageView;


    /**
     * A simple {@link Fragment} subclass.
     */
    public class GroupsFragment extends Fragment {
        private View groupFragmentView;
        private RecyclerView mGroupsRecyclerView;
        private List<Group> groups;
        private FloatingActionButton mCreateGroup;
        private FirebaseAuth mAuth;
        private FirebaseUser currentUser;
        private FirebaseFirestore db;

        public GroupsFragment() {
            // Required empty public constructor
        }

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mAuth = FirebaseAuth.getInstance();
            currentUser = mAuth.getCurrentUser();
            db = FirebaseFirestore.getInstance();

            groups = new ArrayList<>();
            db.collection("users")
                    .document(currentUser.getUid())
                    .collection("groups")
                    .get()
                    .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                        @Override
                        public void onComplete(@NonNull Task<QuerySnapshot> task) {
                            if (task.isSuccessful()) {
                                for (QueryDocumentSnapshot document : task.getResult()) {
                                    groups.add(document.toObject(Group.class));
                                }

                                Toast.makeText(getActivity(), "Groups received successfully", Toast.LENGTH_SHORT).show();
                            } else {
                                Log.d(MainActivity.TAG, "Error getting document: ", task.getException());
                                Toast.makeText(getContext(), "Failed getting groups", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment

            groupFragmentView = inflater.inflate(R.layout.fragment_groups, container, false);
            mCreateGroup = groupFragmentView.findViewById(R.id.create_group_btn);
            mCreateGroup.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    requestNewGroup();
                }
            });

            initView();
            setLayoutManager();
            setAdapter();

            return groupFragmentView;
        }

        private void initView() {
            mGroupsRecyclerView = groupFragmentView.findViewById(R.id.groups_recycler_view);
        }

        private void setLayoutManager() {
            RecyclerView.LayoutManager layoutManager =
                    new LinearLayoutManager(getActivity());
            mGroupsRecyclerView.setLayoutManager(layoutManager);
        }

        private void setAdapter() {
            GroupsAdapter groupsAdapter = new GroupsAdapter(getContext(), groups);
            mGroupsRecyclerView.setAdapter(groupsAdapter);
        }

        private void requestNewGroup() {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialog);
            builder.setTitle("Enter group name");

            final LinearLayout layout = new LinearLayout(groupFragmentView.getContext());
            layout.setOrientation(LinearLayout.VERTICAL);

            final CircleImageView mGroupImage = new CircleImageView(groupFragmentView.getContext());
            mGroupImage.setId(R.id.set_group_image);
            mGroupImage.setImageResource(R.drawable.group_image);

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(200, 200);
            layout.addView(mGroupImage);

            final EditText mGroupName = new EditText(groupFragmentView.getContext());
            mGroupName.setId(R.id.set_group_name);
            mGroupName.setGravity(Gravity.CENTER);
            mGroupName.setHint("Group name");
            layout.addView(mGroupName);

            builder.setView(layout);

            builder.setPositiveButton("Create", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    EditText mGroupName = layout.findViewById(R.id.set_group_name);
                    String groupName = mGroupName.getText().toString();

                    if (TextUtils.isEmpty(groupName)) {
                        Toast.makeText(getActivity(), "Please write the name of the group", Toast.LENGTH_SHORT).show();
                    } else {
                        createNewGroup(groupName);
                    }
                }
            });

            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    dialogInterface.cancel();
                }
            });

            AlertDialog mCreateGroupDialog = builder.create();
            mCreateGroupDialog.show();
            mCreateGroupDialog.getWindow().setLayout(900, 1200);
        }

        private void createNewGroup(String groupName) {
            Map<String, Object> groupData = new HashMap<String, Object>();
            groupData.put("name", groupName);
            groupData.put("adminID", currentUser.getUid());
            groupData.put("users", Arrays.asList(currentUser.getUid()));
            db.collection("users")
                    .document(currentUser.getUid())
                    .collection("groups")
                    .document(groupName)
                    .set(groupData)
                    .addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {
                            Toast.makeText(getContext(), "Group created successfully", Toast.LENGTH_SHORT).show();
                            sendUserToGroupConversation();
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Log.w(MainActivity.TAG, "Error adding document", e);
                            Toast.makeText(getActivity(), "There was an error processing the request.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
        }

        private void sendUserToGroupConversation() {
            // TODO
        }
    }

Group.java


    package com.example.snakemessenger;
    import java.util.List;

    class Group {
        private String name;
        private String adminID;
        private List<String> users;

        public Group() {

        }

        public Group(String name, String adminID, List<String> users) {
            this.name = name;
            this.adminID = adminID;
            this.users = users;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAdminID() {
            return adminID;
        }

        public void setAdminID(String adminID) {
            this.adminID = adminID;
        }

        public List<String> getUsers() {
            return users;
        }

        public void setUsers(List<String> users) {
            this.users = users;
        }
    }

GroupsAdapter.java


    package com.example.snakemessenger;

    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.List;

    class GroupsAdapter extends RecyclerView.Adapter<GroupsViewHolder> {
        private Context mContext;
        private List<Group> mGroups;

        public GroupsAdapter(Context mContext, List<Group> mGroups) {
            this.mContext = mContext;
            this.mGroups = mGroups;
        }

        @NonNull
        @Override
        public GroupsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(mContext)
                    .inflate(R.layout.group_item, parent, false);

            return new GroupsViewHolder(itemView);
        }

        @Override
        public void onBindViewHolder(@NonNull GroupsViewHolder holder, int position) {
            Group currentGroup = mGroups.get(position);

            holder.getTextViewName().setText(currentGroup.getName());
            holder.getCircleImageViewGroup().setImageResource(R.drawable.group_image);
        }

        @Override
        public int getItemCount() {
            return mGroups.size();
        }
    }

GroupsViewHolder.java


    package com.example.snakemessenger;

    import android.view.View;
    import android.widget.TextView;

    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;

    import de.hdodenhof.circleimageview.CircleImageView;

    class GroupsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private TextView mGroupName;
        private CircleImageView mGroupImage;

        public GroupsViewHolder(@NonNull View itemView) {
            super(itemView);

            mGroupName = itemView.findViewById(R.id.group_name_item);
            mGroupImage = itemView.findViewById(R.id.group_image_item);
            itemView.setOnClickListener(this);
        }

        public TextView getTextViewName() {
            return mGroupName;
        }

        public CircleImageView getCircleImageViewGroup() {
            return mGroupImage;
        }

        @Override
        public void onClick(View view) {
            // TODO
        }
    }

这是 XML 文件:

activity_main.xml


    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <include
                android:id="@+id/main_page_toolbar"
                layout="@layout/app_bar_layout">
            </include>

            <com.google.android.material.tabs.TabLayout
                android:id="@+id/main_tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:tabIndicatorColor="#FFFFFF"
                app:tabMode="fixed"
                app:tabGravity="fill">
            </com.google.android.material.tabs.TabLayout>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.viewpager.widget.ViewPager
            android:id="@+id/main_tabs_pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

app_bar_layout.xml


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/main_app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    </androidx.appcompat.widget.Toolbar>

fragment_groups.xml


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:context=".GroupsFragment">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/groups_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/create_group_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            app:fabSize="normal"
            android:backgroundTint="@color/colorPrimary"
            android:elevation="6dp"
            android:src="@drawable/ic_group_add_black_24dp"
            />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

group_item.xml


    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <de.hdodenhof.circleimageview.CircleImageView
            android:layout_gravity="start"
            android:id="@+id/group_image_item"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:src="@drawable/group_image"/>

        <LinearLayout
            android:layout_marginStart="20dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/group_name_item"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:textSize="25sp"
                android:textStyle="bold"
                android:text="Contact Name"/>
        </LinearLayout>
    </LinearLayout>

很抱歉这篇文章很长,但我不知道如何用更少的语言解释这个问题。我向您提供了所有代码,因为我不确定问题出在哪里。 正如我所说,仅当用户单击 FAB 以创建新组、单击 EditText 以选择名称后,才会显示该列表。 请帮忙。谢谢!

最佳答案

让我们开始这样做:

你看到这个方法了吗:

setAdapter();

从此方法中移动它:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
      ..........
      ..........

      setAdapter();

将其放入对数据库的 get 请求中:

        groups = new ArrayList<>();
        db.collection("users")
                .document(currentUser.getUid())
                .collection("groups")
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : task.getResult()) {
                                groups.add(document.toObject(Group.class));


                            }
                            //here
                             setAdapter();

                            Toast.makeText(getActivity(), "Groups received successfully", Toast.LENGTH_SHORT).show();
                        } else {
                            Log.d(MainActivity.TAG, "Error getting document: ", task.getException());
                            Toast.makeText(getContext(), "Failed getting groups", Toast.LENGTH_SHORT).show();
                        }
                    }
                });

然后将获取请求及其所有内容从 onCreate 移至 onCreateView 正是 setAdapter() 所在的位置。

关于java - Fragment 内的 RecyclerView 未正确显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61296082/

相关文章:

java - 关于 ExtJs 4 加载缓慢的查询

android - 如何在操作栏中扩展导航列表?

android - 如何更改滑动刷新布局android中的可交换区域长度

java - 对具有不同对象的数组列表进行排序

ios - 用户注册并登录 (Firebase Cloudstore iOS)

java - 这里可以使用Java String格式吗

java - 如何在 main 和 method 中使用 Scanner

javac - OpenJDK和Oracle中匿名内部类直接调用外部类实例方法有什么区别?

iOS Firebase Facebook 身份验证错误

ios - 控制台中的 Firebase JSON 位置