我未能解决此问题,希望任何人都可以帮助我。我是Android的新手,但是我进行了研究,但谷歌搜索的技巧都没有帮助我将两个RecyclerViews片段放在一个ViewPager中。
我在ExistingClientActivity中查询数据库。数据库(Room)访问位于AsyncTask方法中,该方法可以正常运行并填充我的VisitsWrapper。
public class VisitsWrapper {
List<Service> past;
List<Service> future;
}
在我的ExistingClientActivity内部,一切正常,我得到了正确的查询结果。如果我要直接从Activity中显示RecyclerView,它会很好地工作,但是我需要两个RecyclerViews才能在两个不同的选项卡上显示单独的数据。
我在尝试将服务列表传递给Fragment时遇到了第一个问题。
请在下面查看我的代码,我肯定做错了什么,因为我收到了NullPointerException或空的RecyclerView。
ExistingClientActivity.java
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.google.android.material.tabs.TabLayout;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentTransaction;
import androidx.viewpager.widget.ViewPager;
public class ExistingClientActivity extends AppCompatActivity {
private long clientId;
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_existing_client);
Bundle b = getIntent().getExtras();
clientId = -1;
if (b != null) {
clientId = b.getLong("clientId");
}
fetchVisits();
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new ExistingClientDetailsFragment(), getResources().getString(R.string.clientData));
adapter.addFragment(new ExistingClientVisitsFragment(), getResources().getString(R.string.clientVisitsFuture));
adapter.addFragment(new ExistingClientPastVisitsFragment(), getResources().getString(R.string.clientVisitsPast));
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
private void fetchVisits() {
class GetVisits extends AsyncTask<Void, Void, VisitsWrapper> {
VisitsWrapper vw = new VisitsWrapper();
@Override
protected VisitsWrapper doInBackground(Void... voids) {
List<Service> visitList = DatabaseClient
.getInstance(getApplicationContext())
.getAppDatabase()
.serviceDao()
.findServicesByClientId(clientId);
List<Service> visitListPast = new ArrayList<>();
List<Service> visitListFuture = new ArrayList<>();
Calendar currentDateTime = Calendar.getInstance();
for (Service visit : visitList) {
String visitDate = visit.getServiceDate();
String visitEndTime = visit.getEndTime();
String[] visitDateSplitted = visitDate.split("-");
String[] visitEndTimeSplitted = visitEndTime.split(":");
if (visitDateSplitted.length == 3 && visitEndTimeSplitted.length == 2) {
Integer day = Integer.valueOf(visitDateSplitted[0]);
Integer month = Integer.valueOf(visitDateSplitted[1]);
Integer year = Integer.valueOf(visitDateSplitted[2]);
Integer hour = Integer.valueOf(visitEndTimeSplitted[0]);
Integer minute = Integer.valueOf(visitEndTimeSplitted[0]);
Calendar dateTime = Calendar.getInstance();
dateTime.set(year,month,day,hour,minute);
if (dateTime.before(currentDateTime)) {
visitListPast.add(visit);
} else {
visitListFuture.add(visit);
}
Log.w("========== LIST PAST ========== : ", "PAST LIST fetchVisits: " + visitListPast);
Log.w("========== LIST FUTURE ========== : ", "FUTURE LIST fetchVisits: " + visitListFuture);
}
}
if (!visitListPast.isEmpty()) {
Collections.sort(visitListPast, new Comparator<Service>() {
@Override
public int compare(Service lhs, Service rhs) {
return lhs.getServiceDate().compareTo(rhs.getServiceDate());
}
});
}
if (!visitListFuture.isEmpty()) {
Collections.sort(visitListFuture, new Comparator<Service>() {
@Override
public int compare(Service lhs, Service rhs) {
return lhs.getServiceDate().compareTo(rhs.getServiceDate());
}
});
}
vw.past = visitListPast;
vw.future = visitListFuture;
return vw;
}
@Override
protected void onPostExecute(VisitsWrapper vw) {
super.onPostExecute(vw);
Log.w("========== LIST PAST ========== : ", "PAST LIST onPostExecute: " + vw.past);
Log.w("========== LIST FUTURE ========== : ", "FUTURE LIST onPostExecute: " + vw.future);
pastVisitsInstance((Serializable)vw.past);
futureVisitsInstance((Serializable)vw.future);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
viewPager = findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.recycler_view_serviceFutureList, futureVisitsInstance((Serializable)vw.future));
ft.commit();
FragmentManager fm2 = getSupportFragmentManager();
FragmentTransaction ft2 = fm2.beginTransaction();
ft2.replace(R.id.recycler_view_servicePastList,pastVisitsInstance((Serializable)vw.past));
ft2.commit();
}
}
GetVisits gv = new GetVisits();
gv.execute();
}
public class VisitsWrapper {
List<Service> past;
List<Service> future;
}
public static ExistingClientPastVisitsFragment pastVisitsInstance(Serializable serviceList) {
ExistingClientPastVisitsFragment pastVisitsFragment = new ExistingClientPastVisitsFragment();
Bundle bundlePast = new Bundle();
bundlePast.putSerializable("pastVisits", serviceList);
pastVisitsFragment.setArguments(bundlePast);
Log.w("========== LIST PAST ========== : ", "PAST LIST bundlePast: " + serviceList);
return pastVisitsFragment;
}
public static ExistingClientVisitsFragment futureVisitsInstance(Serializable serviceList) {
ExistingClientVisitsFragment futureVisitsFragment = new ExistingClientVisitsFragment();
Bundle bundleFuture = new Bundle();
bundleFuture.putSerializable("futureVisits", serviceList);
futureVisitsFragment.setArguments(bundleFuture);
Log.w("========== LIST FUTURE ========== : ", "FUTURE LIST bundleFuture: " + serviceList);
return futureVisitsFragment;
}
}
ExistingClientVisitsFragment.java(此片段内的调试日志从不包含任何记录)
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.List;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class ExistingClientVisitsFragment extends Fragment implements ServiceAdapter.ServiceAdapterListener {
public ExistingClientVisitsFragment() {}
private List<Service> visitListFuture;
private RecyclerView recyclerViewFuture;
public ServiceAdapter adapterFuture;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
if (args != null) {
visitListFuture = (List<Service>) args.getSerializable("futureVisits");
}
Log.w("========== LIST FUTURE ========== : ", "FUTURE LIST inside fragment: " + visitListFuture);
final View view = inflater.inflate(R.layout.fragment_existing_client_child, container, false);
recyclerViewFuture = view.findViewById(R.id.recycler_view_serviceFutureList);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this.getActivity());
recyclerViewFuture.setLayoutManager(mLayoutManager);
adapterFuture = new ServiceAdapter(view.getContext(), visitListFuture, ExistingClientVisitsFragment.this);
adapterFuture.setServiceList(visitListFuture);
recyclerViewFuture.setAdapter(adapterFuture);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle args = getArguments();
if (args != null) {
visitListFuture = (List<Service>) args.getSerializable("futureVisits");
}
Log.w("========== LIST FUTURE ========== : ", "ON VIEW CREATED: " + visitListFuture);
}
@Override
public void onServiceSelected(Service service) {
Toast.makeText(getActivity().getApplicationContext(), "Selected: " + service.getStartTime() + " " + service.getEndTime() + ", "
+ service.getServiceDate() + ", ID: " + service.getId() + ", Client ID: " + service.getClientId(), Toast.LENGTH_LONG).show();
}
}
ServiceAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import androidx.recyclerview.widget.RecyclerView;
public class ServiceAdapter extends RecyclerView.Adapter<ServiceAdapter.MyViewHolder> {
private Context context;
private List<Service> serviceList;
private ServiceAdapterListener listener;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView type, date, startTime, endTime;
public MyViewHolder(View view) {
super(view);
type = view.findViewById(R.id.serviceType);
date = view.findViewById(R.id.serviceDate);
startTime = view.findViewById(R.id.serviceTime);
endTime = view.findViewById(R.id.serviceEndTime);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onServiceSelected(serviceList.get(getAdapterPosition()));
}
});
}
}
public ServiceAdapter(Context context, List<Service> serviceList, ServiceAdapterListener listener) {
this.context = context;
this.listener = listener;
this.serviceList = serviceList;
}
public void setServiceList(List<Service> services) {
this.serviceList = services;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.service_row_item, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
final Service service = serviceList.get(position);
holder.type.setText(service.getType());
holder.date.setText(service.getServiceDate());
holder.startTime.setText(service.getStartTime());
holder.endTime.setText(service.getEndTime());
}
@Override
public int getItemCount() {
Integer size;
try {
size = serviceList.size();
} catch (Exception e) {
size = 0;
}
return size;
}
public interface ServiceAdapterListener {
void onServiceSelected(Service service);
}
}
activity_existing_client.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ExistingClientActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
fragment_existing_client_visits.xml(尝试将RecyclerView 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ExistingClientVisitsFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_serviceFutureList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_marginTop="55dp"/>
</FrameLayout>
我在这里做错了什么?我遵循了多个教程,检查了多个类似的问题-似乎没有任何效果。我必须缺少一些基本的Android知识-任何提示都将不胜感激。
关于, 汤姆
答案 0 :(得分:0)
我设法通过使用SharedPreferences将序列化的ArrayList从Activity传递到Fragments来解决我的问题。如果有更好的方法可以做到这一点,请告诉我!