recylerView 未显示在应用程序中
Posted
技术标签:
【中文标题】recylerView 未显示在应用程序中【英文标题】:the recylerView does not shown in the app 【发布时间】:2020-06-13 09:04:50 【问题描述】:嘿,我是使用 android 的新手,我用这个应用程序制作了我正在学习的教程,当我尝试在 Fragment 中工作时,该教程从 MainActivity.java 读取和写入数据。
尽管应用程序没有显示任何错误,但 Firebase 实时数据库的 JSON 数据并未按预期显示在 RecylerView 中。
这是我的文件
MainActivity.java
package com.example.plutus;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class MainActivity extends AppCompatActivity
private TaskFragment taskFragment;
private TimeFragment timeFragment;
private HabitFragment habitFragment;
private HourFragment hourFragment;
private BottomNavigationView mMainNav;
private FrameLayout mMainFrame;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainNav = (BottomNavigationView) findViewById(R.id.main_nav);
mMainFrame = (FrameLayout) findViewById(R.id.main_frame);
taskFragment = new TaskFragment();
timeFragment = new TimeFragment();
habitFragment = new HabitFragment();
hourFragment = new HourFragment();
setFragment(taskFragment);
mMainNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener()
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item)
switch (item.getItemId())
case R.id.nav_task:
setFragment(taskFragment);
return true;
case R.id.nav_time:
setFragment(timeFragment);
return true;
case R.id.nav_habit:
setFragment(habitFragment);
return true;
case R.id.nav_hour:
setFragment(hourFragment);
return true;
default:
return false;
);
private void setFragment(Fragment fragment)
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_frame, fragment);
fragmentTransaction.commit();
TaskAdapter.java
package com.example.plutus;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.MyViewHolder>
ValueEventListener context;
ArrayList<MyTasks> myTasks;
public TaskAdapter(ValueEventListener c, ArrayList<MyTasks> p)
context = c;
myTasks = p;
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
return new MyViewHolder(LayoutInflater.from((Context) context).inflate(R.layout.task_item, parent, false));
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position)
holder.tasktitle.setText(myTasks.get(position).getTasktitle());
@Override
public int getItemCount()
return myTasks.size();
class MyViewHolder extends RecyclerView.ViewHolder
TextView tasktitle;
public MyViewHolder(@NonNull View itemView)
super(itemView);
tasktitle = (TextView) itemView.findViewById(R.id.tasktitletext);
TaskFragment.java
package com.example.plutus;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
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;
/**
* A simple @link Fragment subclass.
*/
public class TaskFragment extends Fragment
//Firebase Json integration
RecyclerView ourTasks;
ArrayList<MyTasks> list;
TaskAdapter taskAdapter;
public TaskFragment()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_task, container, false);
ourTasks = rootView.findViewById(R.id.ourTasks);
ourTasks.setLayoutManager(new LinearLayoutManager(getActivity()));
list = new ArrayList<MyTasks>();
// Inflate the layout for this fragment
DatabaseReference taskDatabaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference taskuser = taskDatabaseReference.child("Task1").child("tasktitle");
taskuser.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
for (DataSnapshot dataSnapshot1: dataSnapshot.getChildren())
MyTasks p = dataSnapshot1.getValue(MyTasks.class);
list.add(p);
taskAdapter = new TaskAdapter(this, list);
ourTasks.setAdapter(taskAdapter);
taskAdapter.notifyDataSetChanged();
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
Toast.makeText(getContext(), "I'm fetching this", Toast.LENGTH_SHORT).show();
);
return rootView;
;
MyTasks.java
package com.example.plutus;
public class MyTasks
String tasktitle;
public MyTasks()
public MyTasks(String tasktitle)
this.tasktitle = tasktitle;
public String getTasktitle()
return tasktitle;
public void setTasktitle(String tasktitle)
this.tasktitle = tasktitle;
我不明白真正的问题在哪里。
编辑:包含的 JSON 文件。
"Plutus":
"Task1":
"tasktitle":"Create an awesome app"
,
"Task2":
"tasktitle":"Learn More Android"
,
"Task3":
"tasktitle":"Learn Android Pentesting too"
,
"Task4":
"tasktitle":"Oi don't forget Bug Hunting"
【问题讨论】:
Stack Overflow 是一个非常低效的交互式调试器,因此很难帮助处理如此大量的代码。如果你在调试器中运行你的代码,你的onDataChange
会被调用吗?如果是这样,如果您逐步执行该方法会发生什么? p
是否包含您期望的数据?您越能帮助我们找到发生故障的特定线路,我们就越有可能提供帮助。
我通过调试器运行它,实际上onDataChange
确实被调用了,尽管内部的 for 循环没有被执行直接跳转到 for 循环之后,而且 onCancelled
也没有被调用。也因为 for 循环不起作用,数组列表保持不变。
如果onDataChange
被调用,但它没有进入你的循环,这意味着taskuser
没有数据。如果您编辑您的问题以包含您尝试显示的 JSON(作为文本,请不要截图),这可能会很有用。您可以通过单击Firebase Database console 上溢出菜单 (⠇) 中的“导出 JSON”链接来获取此信息。
我现在已经在问题中包含了 JSON 文件。
【参考方案1】:
您的代码中存在一些问题:
您没有在代码中处理 JSON 的Plutus
级别。
您的行为好像快照中可以有多个节点,但实际上您加载的是一个非常特定的节点。所以你不需要循环getChildren()
。
由于您只加载title
节点,因此结果不是MyTasks
。
要仅加载一项任务的标题,您可以执行以下操作:
DatabaseReference taskDatabaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference taskuser = taskDatabaseReference.child("Plutus/Task1/tasktitle");
taskuser.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
Log.i("Firebase", dataSnapshot.getValue(String.class));
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
throw databaseError.toException(); // make sure to show the programming error
);
要加载单个任务,但要加载整个任务,它会是这样的:
DatabaseReference taskDatabaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference taskuser = taskDatabaseReference.child("Plutus/Task1");
taskuser.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
MyTasks p = dataSnapshot.getValue(MyTasks.class);
Log.i("Firebase", p.toString());
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
throw databaseError.toException(); // make sure to show the programming error
);
要加载所有任务,并将它们添加到适配器/视图,它会是这样的:
taskAdapter = new TaskAdapter(this, list);
ourTasks.setAdapter(taskAdapter);
DatabaseReference taskDatabaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference taskuser = taskDatabaseReference.child("Plutus");
taskuser.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
for (DataSnapshot taskSnapshot: dataSnapshot.getChildren())
MyTasks p = taskSnapshot.getValue(MyTasks.class);
list.add(p);
taskAdapter.notifyDataSetChanged();
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
throw databaseError.toException(); // make sure to show the programming error
);
您会注意到我在这里将适配器从侦听器中拉出。不需要每次数据发生变化时都重新构建一个新的适配器,而是可以只更新list
中的数据,然后通知适配器,让它更新UI。
【讨论】:
这很有效,虽然必须做一些改变是 TaskAdapter 现在它从 firebase 数据库加载所有的 tastitle。 感谢您的更新!很高兴听到你成功了。 :)以上是关于recylerView 未显示在应用程序中的主要内容,如果未能解决你的问题,请参考以下文章
如何在片段内的 recylerview 列表中显示 SQLite 数据库数据?
使用CustomLists数组显示recylerview数据