簡體   English   中英

帶有片段空指針異常的 Android RecyclerView 適配器

[英]Android RecyclerView adapter with fragment null pointer exception

嗨,我是 Android 新手,遇到了 Recycler View 和 Fragment 的問題。 有 3 個可以滑動的片段,並且片段中有一個帶有適配器的回收器視圖。 我從http://developer.android.com/training/implementing-navigation/lateral.html得到了一個示例代碼,但我在 List 對象中得到了空指針異常。 提前致謝。 我的代碼如下所示:

public class TripHistoryActivity extends FragmentActivity implements ActionBar.TabListener{
private static final String TAG = "TripHistoryActivity";
private CommonDBHelper commonDBHelper;

private List<Trip> allTrips;
private ArrayList<Trip> currentTrips;
private ArrayList<Trip> pastTrips;
private ArrayList<Trip> futureTrips;

AppSectionsPagerAdapter mAppSectionsPagerAdapter;

ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_trip_history);
    commonDBHelper = new CommonDBHelper(this);
    TripDBHelper tripDBHelper = new TripDBHelper(commonDBHelper.getWritableDatabase());

    allTrips = tripDBHelper.getAllTrips();
    currentTrips = new ArrayList<>();
    pastTrips = new ArrayList<>();
    futureTrips = new ArrayList<>();
    Calendar calendar = Calendar.getInstance();
    int currentDay = calendar.get(calendar.DAY_OF_MONTH);
    int currentMonth = calendar.get(calendar.MONTH);
    int currentYear = calendar.get(calendar.YEAR);
    for (Trip trip : allTrips) {

        String date = trip.getTime().substring(0, trip.getTime().indexOf(" "));
        String[] dates = date.split("/");
        if (currentYear < Integer.valueOf(dates[2])) {
            futureTrips.add(trip);
        }
        else if (currentYear > Integer.valueOf(dates[2])
                || currentMonth > Integer.valueOf(dates[0])
                || currentDay > Integer.valueOf(dates[1])) {
            pastTrips.add(trip);
        }
        else {
            currentTrips.add(trip);
        }
    }

    mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
    final ActionBar actionBar = getActionBar();
    actionBar.setHomeButtonEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mAppSectionsPagerAdapter);
    mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            // When swiping between different app sections, select the corresponding tab.
            // We can also use ActionBar.Tab#select() to do this if we have a reference to the
            // Tab.
            actionBar.setSelectedNavigationItem(position);
        }
    });

    for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) {
        // Create a tab with text corresponding to the page title defined by the adapter.
        // Also specify this Activity object, which implements the TabListener interface, as the
        // listener for when this tab is selected.
        actionBar.addTab(
                actionBar.newTab()
                        .setText(mAppSectionsPagerAdapter.getPageTitle(i))
                        .setTabListener(this));
    }
}


@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in the ViewPager.
    mViewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary
 * sections of the app.
 */
public class AppSectionsPagerAdapter extends FragmentPagerAdapter {

    public AppSectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public android.support.v4.app.Fragment getItem(int i) {
        switch (i) {
            case 0:
                android.support.v4.app.Fragment currentTripsFragment = new CurrentTripsFragment();
                Bundle currentTripsBundle = new Bundle();
                currentTripsBundle.putParcelableArrayList("currentTrips", currentTrips);
                currentTripsFragment.setArguments(currentTripsBundle);
                return currentTripsFragment;

            case 1:
                android.support.v4.app.Fragment pastTripsFragment = new PastTripsFragment();
                Bundle pastTripsBundle = new Bundle();
                pastTripsBundle.putParcelableArrayList("pastTrips", pastTrips);
                pastTripsFragment.setArguments(pastTripsBundle);
                return pastTripsFragment;

            default:
                android.support.v4.app.Fragment futureTripsFragment = new FutureTripsFragment();
                Bundle futureTripsBundle = new Bundle();
                futureTripsBundle.putParcelableArrayList("futureTrips", futureTrips);
                futureTripsFragment.setArguments(futureTripsBundle);
                return futureTripsFragment;
        }
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Current Trips";
            case 1:
                return "Past Trips";
            case 2:
                return "Future Trips";
            default:
                return "Fault";
        }
    }
}

/**
 * A fragment that launches other parts of the demo application.
 */
public static class CurrentTripsFragment extends android.support.v4.app.Fragment {
    private RecyclerView mRecyclerView;
    private Context context;
    List<Trip> currentTrips;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_current_trips, container, false);
        context = rootView.getContext();
        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);

        currentTrips = getArguments().getParcelableArrayList("currentTrips");
        Log.d(TripHistoryActivity.TAG, String.valueOf(currentTrips == null));

        RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
        mRecyclerView.setLayoutManager(manager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
        mRecyclerView.setAdapter(cardViewAdapter);
        cardViewAdapter.setOnItemClick(new CardViewAdapter.OnItemClick() {
            @Override
            public void onItemClick(int position) {
                handleItemClick(position);
            }
        });

        return rootView;
    }

    public void handleItemClick (int position) {
        Toast.makeText(context, "Clicked " + position, Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(context, ViewTripActivity.class);
        intent.putExtra("trip", currentTrips.get(position));
        startActivity(intent);
    }
}

還有 2 個與此相同的片段,所以我省略了它們。

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.nyu.cs9033.eta.R;
import com.nyu.cs9033.eta.models.Trip;

import java.util.List;

/**
 * Created by Ray on 2016/4/2.
 */
public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.CardViewHolder> {
    private final List<Trip> trips;

    public CardViewAdapter (List<Trip> trips) {
        this.trips = trips;
    }

    public interface OnItemClick {
        public void onItemClick(int position);
    }

    private OnItemClick onItemClick;

    public void setOnItemClick (OnItemClick onItemClick) {
        this.onItemClick = onItemClick;
    }

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

    @Override
    public void onBindViewHolder(final CardViewHolder holder, final int position) {
        holder.name.setText(trips.get(position).getName());
        holder.location.setText(trips.get(position).getLocation());
        holder.time.setText(trips.get(position).getTime());
        if (onItemClick != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClick.onItemClick(position);
                }
            });
        }
    }

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

    class CardViewHolder extends RecyclerView.ViewHolder {
        private TextView name;
        private TextView location;
        private TextView time;

        public CardViewHolder (View view) {
            super(view);
            name = (TextView) view.findViewById(R.id.card_trip_name);
            location = (TextView) view.findViewById(R.id.card_trip_location);
            time = (TextView) view.findViewById(R.id.card_trip_time);
        }
    }

}

這是 logcat 所說的:

FATAL EXCEPTION: mainProcess: com.nyu.cs9033.eta, PID: 14018
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()'
on a null object reference
at com.nyu.cs9033.eta.adapters.CardViewAdapter.getItemCount(CardViewAdapter.java: 57)
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java: 2357)
at android.view.View.measure(View.java: 18796)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java: 715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java: 461)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at android.view.View.measure(View.java: 18796)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java: 1488)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java: 446)
at android.view.View.measure(View.java: 18796)
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: 18796)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java: 2108)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java: 1224)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java: 1460)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java: 1115)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java: 6023)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java: 858)
at android.view.Choreographer.doCallbacks(Choreographer.java: 670)
at android.view.Choreographer.doFrame(Choreographer.java: 606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java: 844)
at android.os.Handler.handleCallback(Handler.java: 739)
at android.os.Handler.dispatchMessage(Handler.java: 95)
at android.os.Looper.loop(Looper.java: 148)
at android.app.ActivityThread.main(ActivityThread.java: 5422)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 616)

您應該從onCreate()而不是onCreateView()獲得包。 在您的 Fragment 類中嘗試以下更改:

public static class CurrentTripsFragment extends android.support.v4.app.Fragment {

private RecyclerView mRecyclerView;
private Context context;
List<Trip> currentTrips;

@Override
public void onCreate(Bundle savedInstanceState){
    super().onCreate(savedInstanceState);

    if(getArguments()!= null){
        currentTrips = getArguments().getParcelableArrayList("currentTrips");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_current_trips, container, false);
    context = rootView.getContext();
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);

    Log.d(TripHistoryActivity.TAG, String.valueOf(currentTrips == null));

    RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
    mRecyclerView.setLayoutManager(manager);
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
    mRecyclerView.setAdapter(cardViewAdapter);
    cardViewAdapter.setOnItemClick(new CardViewAdapter.OnItemClick() {
        @Override
        public void onItemClick(int position) {
            handleItemClick(position);
        }
    });

    return rootView;
}

public void handleItemClick (int position) {
    Toast.makeText(context, "Clicked " + position, Toast.LENGTH_SHORT).show();
    Intent intent = new Intent(context, ViewTripActivity.class);
    intent.putExtra("trip", currentTrips.get(position));
    startActivity(intent);
}
}

您的列表中出現空指針異常,用於在回收站視圖中顯示列表項...請檢查您是否在列表中獲取數據...問題似乎出在此處:

CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);

和這里:

currentTrips = getArguments().getParcelableArrayList("currentTrips");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM