简体   繁体   中英

Button from Fragment is Crashing the app

I put a Button in fragment with the corresponding listener. Every time I call on this activity the app crashes. Logcat show a null pointer exception. The code below is a snippet from the Fragment class.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_carprofile_list, container, false);

    // Set the adapter
    if (view instanceof RecyclerView) {
        Context context = view.getContext();
        RecyclerView recyclerView = (RecyclerView) view;
        if (mColumnCount <= 1) {
            recyclerView.setLayoutManager(new LinearLayoutManager(context));
        } else {
            recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
        }
        recyclerView.setAdapter(new MyCarProfileRecyclerViewAdapter(carProfileContent.ITEMS, mListener));
    }

    Button imgbtn = (Button) view.findViewById(R.id.editCarProfileButton);
    imgbtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivity(new Intent(getActivity(),ReserveActivity.class));
        }
    });

    return view;
}

Logcat shows:

FATAL EXCEPTION: main
Process: com.example.app, PID: 13571
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.CarProfileListActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.mikepuno.parkeazy.CarProfileFragment.onCreateView(CarProfileFragment.java:78)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3221)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3171)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:192)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:560)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1174)
at android.app.Activity.performStart(Activity.java:5353)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2340)

I've been looking at multiple similar issues here but it just don't seem to work for me. Am I missing anything from the way I added the Button and the listener?

fragment_carprofile_list.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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:id="@+id/list"
    android:name="com.mikepuno.parkeazy.CarProfileFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    app:layoutManager="LinearLayoutManager"
    tools:context="com.mikepuno.parkeazy.CarProfileFragment"
    tools:listitem="@layout/fragment_carprofile" />

fragment_carprofile.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:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/plateNumberTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:textAppearance="?attr/textAppearanceListItem" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/brandTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:textAppearance="?attr/textAppearanceListItem" />

        <TextView
            android:id="@+id/modelTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:textAppearance="?attr/textAppearanceListItem" />

        <TextView
            android:id="@+id/colorTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:textAppearance="?attr/textAppearanceListItem" />

        <Button
            android:id="@+id/editCarProfileButton"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:text="Edit" />

    </LinearLayout>
</LinearLayout>

Adapter Class

public class MyCarProfileRecyclerViewAdapter extends RecyclerView.Adapter<MyCarProfileRecyclerViewAdapter.ViewHolder> {

    private final List<CarProfile> mValues;
    private final OnListFragmentInteractionListener mListener;

    public MyCarProfileRecyclerViewAdapter(List<CarProfile> items, OnListFragmentInteractionListener listener) {
        mValues = items;
        mListener = listener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.fragment_carprofile, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.mItem = mValues.get(position);
        holder.mPlateNumberTextView.setText(mValues.get(position).getPlateNumber());
        holder.mBrandTextView.setText(mValues.get(position).getBrand());
        holder.mModelTextView.setText(mValues.get(position).getModel());
        holder.mColorTextView.setText(mValues.get(position).getColor());

        holder.mView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mListener) {
                    // Notify the active callbacks interface (the activity, if the
                    // fragment is attached to one) that an item has been selected.
                    mListener.onListFragmentInteraction(holder.mItem);
                }
            }
        });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        public final View mView;
        public final TextView mPlateNumberTextView;
        public final TextView mBrandTextView;
        public final TextView mModelTextView;
        public final TextView mColorTextView;
        public CarProfile mItem;

        public ViewHolder(View view) {
            super(view);
            mView = view;
            mPlateNumberTextView = (TextView) view.findViewById(R.id.plateNumberTextView);
            mBrandTextView = (TextView) view.findViewById(R.id.brandTextView);
            mModelTextView = (TextView) view.findViewById(R.id.modelTextView);
            mColorTextView = (TextView) view.findViewById(R.id.colorTextView);
        }

        @Override
        public String toString() {
            return super.toString() + " '" + mPlateNumberTextView.getText() + "'";
        }
    }
}

After you inflate your view

View view = inflater.inflate(R.layout.fragment_carprofile_list, container, false);

you assume that view is RecyclerView. That means root element is recyclerview.

Then trying to find a button inside of that recyclerview by doing

Button imgbtn = (Button) view.findViewById(R.id.editCarProfileButton);

which returns null ofcourse. Then trying to set a click listener on null object.

Looks like your xml file is wrong. If your each row has button that you are trying to find, you need to catch it in your adapter class then notify fragment to do your process.

SOLUTION (EDIT):

Remove these lines from onCreateView in Fragment.

Button imgbtn = (Button) view.findViewById(R.id.editCarProfileButton);
    imgbtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivity(new Intent(getActivity(),ReserveActivity.class));
        }
    });

You have already a interface that notify the fragment. So that we are going to use it for editing.

So the final adapter class should be like

public class MyCarProfileRecyclerViewAdapter extends RecyclerView.Adapter<MyCarProfileRecyclerViewAdapter.ViewHolder> {

private final List<CarProfile> mValues;
private final OnListFragmentInteractionListener mListener;

public MyCarProfileRecyclerViewAdapter(List<CarProfile> items, OnListFragmentInteractionListener listener) {
    mValues = items;
    mListener = listener;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.fragment_carprofile, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    holder.mItem = mValues.get(position);
    holder.mPlateNumberTextView.setText(mValues.get(position).getPlateNumber());
    holder.mBrandTextView.setText(mValues.get(position).getBrand());
    holder.mModelTextView.setText(mValues.get(position).getModel());
    holder.mColorTextView.setText(mValues.get(position).getColor());
}

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

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

    public final TextView mPlateNumberTextView;
    public final TextView mBrandTextView;
    public final TextView mModelTextView;
    public final TextView mColorTextView;
    public CarProfile mItem;

    public ViewHolder(View view) {
        super(view);

        view.setClickable(true); // This is important
        view.setOnClickListener(this);

        mPlateNumberTextView = (TextView) view.findViewById(R.id.plateNumberTextView);
        mBrandTextView = (TextView) view.findViewById(R.id.brandTextView);
        mModelTextView = (TextView) view.findViewById(R.id.modelTextView);
        mColorTextView = (TextView) view.findViewById(R.id.colorTextView);
    }

    public void onClick(View view) {
       if (null != mListener) {
            mListener.onListFragmentInteraction(mValues.get(getAdapterPosition()));
       }
    }

    @Override
    public String toString() {
        return super.toString() + " '" + mPlateNumberTextView.getText() + "'";
    }
   }

Then your fragment

    @Override
    public void onListFragmentInteraction(CarProfile profile) {
        // TODO Pass your profile to ReserverActivity by using bundles.
        startActivity(new Intent(getActivity(), ReserveActivity.class));
    }

You can improve the code by notify fragment on your button click. So your button click listener and notify code must also be in here.

View view = inflater.inflate(R.layout.fragment_carprofile_list, container, false);

You are inflating fragment_carprofile_list.xml , which contains the RecyclerView. There is no mention of Button in that XML, which is why you are getting a NullPointerException

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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