简体   繁体   English

执行 ViewModelProvider.Factory 并且我收到空指针异常

[英]Impementing a ViewModelProvider.Factory and I am getting a null pointer exeception

I believe I am following the code samples that have been provided to me for establishing the ViewModelProvider.Factory.我相信我正在遵循提供给我的用于建立 ViewModelProvider.Factory 的代码示例。 It is happening on this statement in the CheckInRecentList code in the OnAttach method.它发生在 OnAttach 方法的 CheckInRecentList 代码中的这个语句上。 Any assistance you can provide will be appreciated.您可以提供的任何帮助将不胜感激。

mViewModel = new ViewModelProvider(this, viewModelFactory).get(MainViewModel.class); mViewModel = new ViewModelProvider(this, viewModelFactory).get(MainViewModel.class);

Getting the following null pointer exception as shown here获取以下空指针异常,如下所示

02-01 06:08:08.319 22068-22068/com.example.checkingin I/Constraints: onAttach: OnAttach
02-01 06:17:22.773 22068-22068/com.example.checkingin D/AndroidRuntime: Shutting down VM
02-01 06:17:22.773 22068-22068/com.example.checkingin E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.checkingin, PID: 22068
    java.lang.NullPointerException: Attempt to invoke interface method 'androidx.lifecycle.ViewModel androidx.lifecycle.ViewModelProvider$Factory.create(java.lang.Class)' on a null object reference
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at com.example.checkingin.CheckInRecentList.onAttach(CheckInRecentList.java:117)
        at androidx.fragment.app.Fragment.performAttach(Fragment.java:2669)
        at androidx.fragment.app.FragmentStateManager.attach(FragmentStateManager.java:229)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1215)
        at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1240)
        at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1123)
        at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:136)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2117)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2075)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1946)
        at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:303)
        at androidx.fragment.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:238)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
        at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:733)
        at com.google.android.material.appbar.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:95)
        at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1556)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:803)
        at android.view.View.measure(View.java:18788)
        at androidx.drawerlayout.widget.DrawerLayout.onMeasure(DrawerLayout.java:1119)
        at android.view.View.measure(View.java:18788)
        at androidx.drawerlayout.widget.DrawerLayout.onMeasure(DrawerLayout.java:1119)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643)
        at android.view.View.measure(View.java:18788)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2100)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1216)
        a

CheckInRecentList.java CheckInRecentList.java

package com.example.checkingin;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProvider.Factory;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.List;

import static androidx.constraintlayout.widget.Constraints.TAG;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link CheckInRecentList.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link CheckInRecentList#newInstance} factory method to
 * create an instance of this fragment.
 */
public class CheckInRecentList extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    private RecyclerView recyclerView;
    private RecyclerView.Adapter checkInListAdapter;
    //private RecyclerView.LayoutManager layoutManager;
    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;
    private MainViewModel mViewModel;
    private CheckInListAdapter adapter;
    private MainViewModelProviderFactory viewModelFactory;
    private TextView checkInLastDateTime;
    private TextView checkInTitle;
    private TextView checkInDestinationName;
    private TextView checkInComments;

    private OnFragmentInteractionListener mListener;

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

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment CheckInRecentList.
     */
    // TODO: Rename and change types and number of parameters
    public static CheckInRecentList newInstance(String param1, String param2) {
        CheckInRecentList fragment = new CheckInRecentList();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    //      These were originally set up from the recycler view add to the fragment
    //          recyclerView = findViewById(R.id.check_in_recent_recycler_view);

                // use this setting to improve performance if you know that changes
                // in content do not change the layout size of the RecyclerView
                //recyclerView.setHasFixedSize(true);
/*
                // use a linear layout manager
                layoutManager = new LinearLayoutManager(this);
                recyclerView.setLayoutManager(layoutManager);
*/
                // specify an adapter (see also next example)
                //checkInListAdapter = new CheckInListAdapter();
     //           recyclerView.setAdapter(checkInListAdapter);
            }

   @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_check_in_recent_list, container, false);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {

        super.onAttach(context);

        Log.i(TAG, "onAttach: OnAttach");

        mViewModel = new ViewModelProvider(this, viewModelFactory).get(MainViewModel.class);

        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        Log.i(TAG, "onActivityCreated: OnCreateView");

        //mViewModel = new ViewModelProvider(this, viewModelFactory).get(MainViewModel.class);

        checkInLastDateTime = getView().findViewById(R.id.checkInLastDateTime);
        checkInTitle = getView().findViewById(R.id.checkInTitle);
        checkInDestinationName = getView().findViewById(R.id.checkInDestinationName);
        checkInComments = getView().findViewById(R.id.checkInComments);

        listenerSetup();
        observerSetup();
        recyclerSetup();
    }
    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
    private void clearFields() {
        checkInLastDateTime.setText("");
        checkInDestinationName.setText("");
        checkInTitle.setText("");
        checkInComments.setText("");
    }

    private void listenerSetup() {

        Button editCheckInButton = getView().findViewById(R.id.checkInEditButton);
        Button resendCheckInButton = getView().findViewById(R.id.checkInResendButton);

        editCheckInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
        //put in edit check in logic
            }
        });
        resendCheckInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
        //put in resend logic
            }
        });

        }

    private void observerSetup() {

        mViewModel.getAllCheckIn().observe(getViewLifecycleOwner(), new Observer<List<CheckInTable>> ()
{
            @Override
            public void onChanged(@Nullable final List<CheckInTable> checkIn) {
                adapter.setCheckInList(checkIn);
            }
        });

        mViewModel.getSearchCheckInResults().observe(getViewLifecycleOwner(), new Observer<List<CheckInTable>>() {
            @Override
            public void onChanged(@Nullable final List<CheckInTable> checkIn) {

                        if (checkIn.size() > 0) {

                            checkInLastDateTime.setText(checkIn.get(0).getCheckInLastDateTime());
                            checkInDestinationName.setText(checkIn.get(0).getCheckInDestinationName());
                            checkInTitle.setText(checkIn.get(0).getCheckInTitle());
                            checkInComments.setText(checkIn.get(0).getCheckInComments());
                        } else {
                            checkInLastDateTime.setText("None Found");
                        }
                    }
                });
    }
    private void recyclerSetup() {

        RecyclerView recyclerView;

        adapter = new CheckInListAdapter(R.layout.recycler_view_item);
        recyclerView = getView().findViewById(R.id.check_in_recent_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        recyclerView.setAdapter(adapter);
    }
}

MainViewModelProviderFactory主视图模型提供者工厂

package com.example.checkingin;

import android.app.Application;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

import static androidx.constraintlayout.widget.Constraints.TAG;

public class MainViewModelProviderFactory implements ViewModelProvider.Factory {
    private final Application mDataSource;

    public MainViewModelProviderFactory(Application dataSource) {
        mDataSource = dataSource;

    }

    @Override
    @NonNull
    public <T extends ViewModel>
        T create(@NonNull Class<T> modelClass) {
        Log.i(TAG, "MainViewModelProviderFactory: ");
        if (modelClass.isAssignableFrom(MainViewModel.class)) {
            Log.i(TAG, "create: is assignable");
            return (T) new MainViewModel(mDataSource);
        }
        //noinspection unchecked
        throw new IllegalArgumentException("Unknown ViewModel class");
    }}

MainViewModel.java主视图模型.java

package com.example.checkingin;
import android.app.Application;
import android.util.Log;

import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import java.util.List;

import static androidx.constraintlayout.widget.Constraints.TAG;

public class MainViewModel extends AndroidViewModel {

    private CheckInRecipientsTableRepository checkInRecipientsTableRepository;
    private LiveData<List<CheckInRecipientsTable>> allRecipients;
    private MutableLiveData<List<CheckInRecipientsTable>> searchRecipientResults;

    private ContactGroupsTableRepository contactGroupsTableRepository;
    private LiveData<List<ContactGroupsTable>> allContactGroups;
    private MutableLiveData<List<ContactGroupsTable>> searchContactGroupsResults;

    private CheckInTableRepository checkInTableRepository;
    private LiveData<List<CheckInTable>> allCheckIn;
    private MutableLiveData<List<CheckInTable>> searchCheckInResults;

    public MainViewModel (Application application) {
        super(application);
        Log.i(TAG, "MainViewModel: In the Main View Model");
        checkInRecipientsTableRepository = new CheckInRecipientsTableRepository(application);
        allRecipients = checkInRecipientsTableRepository.getAllCheckInRecipients();
        searchRecipientResults = checkInRecipientsTableRepository.getSearchRecipientResults();

        checkInTableRepository = new CheckInTableRepository(application);
        allCheckIn = checkInTableRepository.getAllCheckIn();
        searchCheckInResults = checkInTableRepository.getSearchCheckInResults();

        contactGroupsTableRepository = new ContactGroupsTableRepository(application);
        allContactGroups = contactGroupsTableRepository.getAllContactGroups();
        searchContactGroupsResults = contactGroupsTableRepository.getSearchContactGroupsResults();
    }


    MutableLiveData<List<CheckInRecipientsTable>> getSearchRecipientResults() {
        return getSearchRecipientResults();
    }
    LiveData<List<CheckInRecipientsTable>> getAllCheckInRecipients() {
        return getAllCheckInRecipients();
    }

    public void insertCheckInRecipientsTable(CheckInRecipientsTable checkInRecipientsTable) {
        checkInRecipientsTableRepository.insertCheckInRecipientsTable(checkInRecipientsTable);
    }
    public void deleteCheckInRecipient(int checkInPrimaryKey) {
        checkInRecipientsTableRepository.deleteCheckInRecipient(checkInPrimaryKey);
    }
    public void findCheckInRecipient(int checkInPrimaryKey) {
        checkInRecipientsTableRepository.findCheckInRecipient(checkInPrimaryKey);
    }


    MutableLiveData<List<ContactGroupsTable>> getSearchContactGroupsResults() {
        return getSearchContactGroupsResults();
    }
    LiveData<List<ContactGroupsTable>> getAllContactGroups() {
        return getAllContactGroups();
    }

    public void insertContactGroupsTable(ContactGroupsTable contactGroupsTable) {
        contactGroupsTableRepository.insertContactGroups(contactGroupsTable);
    }
    public void deleteContactGroups(int contactGroupsTablePrimaryKey) {
        contactGroupsTableRepository.deleteContactGroups(contactGroupsTablePrimaryKey);
    }
    public void findContactGroups(int contactGroupsTablePrimaryKey) {
        contactGroupsTableRepository.findContactGroups(contactGroupsTablePrimaryKey);
    }

    MutableLiveData<List<CheckInTable>> getSearchCheckInResults() {
        return getSearchCheckInResults();
    }
    LiveData<List<CheckInTable>> getAllCheckIn() {
        return getAllCheckIn();
    }

    public void insertCheckInTable(CheckInTable checkInTable) {
        checkInTableRepository.insertCheckIn(checkInTable);
    }
    public void deleteCheckIn(int checkInTablePrimaryKey) {
        checkInTableRepository.deleteCheckIn(checkInTablePrimaryKey);
    }
    public void findCheckIn(int checkInTablePrimaryKey) {
        checkInTableRepository.findCheckIn(checkInTablePrimaryKey);
    }
}

You should pass an initialized object of ViewModelProvider.Factory interface to ViewModelProvider constructor.您应该将ViewModelProvider.Factory接口的初始化对象传递给ViewModelProvider构造函数。

private MainViewModelProviderFactory viewModelFactory;

// Note that it is better to use onCreate or onCreateView for initialization.   
// Since your ViewModel usually should be alive at a time, when `onAttach` is called.
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    viewModelFactory = new MainViewModelProviderFactory(context.getApplicationContext());
    mViewModel = new ViewModelProvider(this, viewModelFactory).get(MainViewModel.class);

}

It is unusual practice to pass application class as data source, use context instead.将应用程序类作为数据源传递,而不是使用上下文是不寻常的做法。 So change your MainViewModelProviderFactory class:所以改变你的MainViewModelProviderFactory类:

private final Context mDataSource;

public MainViewModelProviderFactory(Context appContext) {
    mDataSource = appContext;
}

Or if you don't want to do so, change line in onAttach或者,如果您不想这样做,请更改onAttach

viewModelFactory = new MainViewModelProviderFactory((Application)context.getApplicationContext());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM