java.lang.NullPointerException:尝试调用虚方法'java.lang.String com.solaris.timster.model.Post.getTitle()'

时间:2016-06-24 23:51:06

标签: java android

我知道有很多关于nullpointexeception的问题,但如果我能找到错误的地方,我不会在这里问这个问题。所以当我到达列表底部并尝试使用方法加载更多数据时,我收到此错误。我正在使用recyclerview这样做。所以第一次加载所有数据,但是当我尝试加载更多时,我会在标题中提到错误。这是代码:

public class ProfileUserFragment extends Fragment implements OnBackPressedListener {

private ResideMenu resideMenu;
private SmoothRecyclerView mRecyclerView;
private PostListAdapter mAdapter;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View parentView = inflater.inflate(R.layout.fragment_profile, container, false);
    setUpViews(parentView);
    initList(parentView);
    return parentView;
}

private void initList(View view) {
    bindData();
    mRecyclerView = (SmoothRecyclerView) view.findViewById(R.id.list);
    mRecyclerView.setHasFixedSize(true);
    LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
    mRecyclerView.setLayoutManager(manager);
    mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration(getActivity()));
    mAdapter      = new PostListAdapter(getActivity());

    mRecyclerView.setAdapter(mAdapter);

    // Load more data when user reach bottom
    mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
        @Override
        public void onLoadMore() {
            // add null , so the adapter will check view_type and show progress bar at bottom
            mPosts.add(null);
            mAdapter.notifyItemInserted(mPosts.size() - 1);

            // Load data
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Remove loading item
                    mPosts.remove(mPosts.size() - 1);
                    mAdapter.notifyItemRemoved(mPosts.size());

                    // Load data
                    int start = mPosts.size();
                    int end   = start + 20;
                    for (int i = start + 1; i <= end; i++) {
                        Post post = new Post();
                        post.setTitle("Title ");
                        post.setDesc("Desc ");
                        post.setTimestamp("Time ");
                        mPosts.add(post);
                    }

                    mAdapter.setLoaded();
                    mAdapter.notifyDataSetChanged();
                }
            }, 2000);
        }
    });
}

private void setUpViews(View view) {
    HomeActivity parentActivity = (HomeActivity) getActivity();
    resideMenu = parentActivity.getResideMenu();
    ImageButton imageButton = (ImageButton) view.findViewById(R.id.drawer_menu);
    imageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            resideMenu.openMenu(ResideMenu.DIRECTION_LEFT);
        }
    });
}

private void bindData() {
    mPosts.clear();
    for (int i = 1; i <= 20; i++) {
        Post post = new Post();
        post.setTitle("Title " + i);
        post.setDesc("Desc " + i);
        post.setTimestamp("Time " + i);
        mPosts.add(post);
    }
}

@Override
public void onBackPressed() {
    resideMenu.openMenu(ResideMenu.DIRECTION_LEFT);
}

private List<Post> mPosts = new ArrayList<>();

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

    private Context mContext;
    private OnLoadMoreListener mOnLoadMoreListener;

    private final int VIEW_TYPE_ITEM    = 0;
    private final int VIEW_TYPE_LOADING = 1;

    private boolean isLoading;
    private int visibleThreshold = 2;
    private int lastVisibleItem, totalItemCount;

    public PostListAdapter(Context context) {
        this.mContext = context;
        final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                totalItemCount  = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();

                if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    // End has been reached
                    // Do something
                    if (mOnLoadMoreListener != null) {
                        mOnLoadMoreListener.onLoadMore();
                    }
                    isLoading = true;
                }
            }
        });
    }

    public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
        this.mOnLoadMoreListener = mOnLoadMoreListener;
    }

    @Override
    public int getItemViewType(int position) {
        return mPosts == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder vh = null;
        if (viewType == VIEW_TYPE_ITEM) {
            View view = LayoutInflater.from(mContext).inflate(
                    R.layout.post_list_item,
                    parent,
                    false);
            vh = new PostHolder(view);
        } else if (viewType == VIEW_TYPE_LOADING){
            View view = LayoutInflater.from(mContext).inflate(
                    R.layout.progress_bar,
                    parent,
                    false);
            vh = new LoadingHolder(view);
        }
        return vh;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof PostHolder) {
            PostHolder postHolder = (PostHolder) holder;
            Post post = mPosts.get(position);
            postHolder.tvPostTitle.setText(post.getTitle());
            postHolder.tvPostDesc.setText(post.getDesc());
            postHolder.tvPostTimestamp.setText(post.getTimestamp());
        } else if (holder instanceof LoadingHolder) {
            LoadingHolder loadingHolder = (LoadingHolder) holder;
            loadingHolder.mProgressBar.setIndeterminate(true);
        }
    }

    @Override
    public int getItemCount() {
        return mPosts == null ? 0 : mPosts.size();
    }

    public class PostHolder extends RecyclerView.ViewHolder {
        MyTextView tvPostTitle;
        MySecondTextView tvPostTimestamp, tvPostDesc;

        public PostHolder(View view) {
            super(view);
            tvPostTitle     = (MyTextView) view.findViewById(R.id.tv_post_title);
            tvPostDesc      = (MySecondTextView) view.findViewById(R.id.tv_post_desc);
            tvPostTimestamp = (MySecondTextView) view.findViewById(R.id.tv_created_at);
        }
    }

    public class LoadingHolder extends RecyclerView.ViewHolder {
        ProgressBar mProgressBar;

        public LoadingHolder(View view) {
            super(view);
            mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar1);
        }
    }

    public void setLoaded() {
        isLoading = false;
    }
}
}

这是我遇到的错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.solaris.timster.model.Post.getTitle()' on a null object reference
                                                                     at com.solaris.timster.fragments.ProfileUserFragment$PostListAdapter.onBindViewHolder(ProfileUserFragment.java:191)
                                                                     at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5471)
                                                                     at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5504)
                                                                     at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4741)
                                                                     at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617)
                                                                     at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994)
                                                                     at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390)
                                                                     at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
                                                                     at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1180)
                                                                     at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1031)
                                                                     at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4061)
                                                                     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
                                                                     at android.view.Choreographer.doCallbacks(Choreographer.java:695)
                                                                     at android.view.Choreographer.doFrame(Choreographer.java:628)
                                                                     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
                                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:158)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

2 个答案:

答案 0 :(得分:2)

更新getItemViewType如下

@Override
public int getItemViewType(int position) {
    return mPosts.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}

这样您就可以检查位置上的项目是否为空。之前您正在检查整个列表是否为空,因此在onBindViewHolder中获取了不正确的视图持有者类型。

答案 1 :(得分:1)

您在mPosts.add(null);中看到了onLoadMore()的来电?也就是说,当空值插入到项目列表中,然后当您在post.getTitle()中调用onBindViewHolder()时,它将导致NullPointerException

您可以做的一件事是检查post中的null是否为onBincViewHolder(),如果只是返回。

或者你可以在第一时间不将空值添加到列表中。

P.S :您正在致电mAdapter.notifyItemRemoved(mPosts.size());,不应该是mAdapter.notifyItemRemoved(mPosts.size()-1);吗?