Несколько фрагментов RecyclerView внутри ViewPager - PullRequest
0 голосов
/ 27 марта 2019

Я не смог решить эту проблему и надеюсь, что кто-нибудь может мне помочь с этим. Я новичок в Android, однако я провел свое исследование, и ни один из советов по поиску в Google не помог мне поместить два фрагмента RecyclerViews в один ViewPager.

Я запрашиваю базу данных в ExistingClientActivity. Доступ к базе данных (комнате) находится в методе AsyncTask, который работает нормально и заполняет мой VisitsWrapper.

public class VisitsWrapper {
    List<Service> past;
    List<Service> future;
}

Внутри моей ExistingClientActivity все работает нормально, и я получаю правильные результаты запроса. Если бы я отображал свой RecyclerView непосредственно из Activity, он бы прекрасно работал, однако мне нужны два RecyclerView для отображения отдельных данных на двух разных вкладках.

Я столкнулся с первой проблемой при попытке передать список сервисов фрагменту.

Пожалуйста, посмотрите на мой код ниже, я, должно быть, делаю что-то не так, потому что я либо получаю 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>

frag_existing_client_visits.xml (еще больше попытался вложить XML-код RecyclerView, вернул мой код к этому, потому что это тоже не помогло)

<?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 - любые советы будут оценены.

С уважением, Том

1 Ответ

0 голосов
/ 28 марта 2019

Мне удалось решить мою проблему, передав сериализованный ArrayList из Activity во фрагменты с помощью SharedPreferences.Если есть лучший способ сделать это, пожалуйста, дайте мне знать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...