简体   繁体   中英

OnItemClickListener for RecyclerView in ViewPager

I am trying to open a url link when I click on a list item in a recyclerview but I keep getting a NullPointerException . I am using a ViewPager, I don't know if this is the cause of the exception, maybe I'm doing something wrong. Please check out my code and logcat below.

This is my adapter:

public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {

private ArrayList<News> mNews = new ArrayList<>();
private static ClickListener clickListener;

public NewsAdapter(ArrayList<News> news) {
    mNews = news;
}

private static String timeConverter(String inputTime) {
    long startTime = 0;
    SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    simpleDate.setTimeZone(TimeZone.getTimeZone("GMT"));
    try {
        Date date = simpleDate.parse(inputTime);
        startTime = date.getTime();
    } catch (ParseException e) {
        e.printStackTrace();
    }

    long currentTime = System.currentTimeMillis();

    long end = currentTime - startTime;

    long seconds = TimeUnit.MILLISECONDS.toSeconds(end);
    long minutes = TimeUnit.SECONDS.toMinutes(seconds);
    long hours = TimeUnit.MINUTES.toHours(minutes);

    if (minutes > 59) {
        return hours + "h";
    }else if (seconds > 59) {
        return minutes + "m";
    }else {
        return seconds + "s";
    }
}

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

@Override
public void onBindViewHolder(NewsHolder holder, int position) {
    String imagePath = mNews.get(position).getImageUrl();
    Picasso.with(holder.mImageView.getContext()).load(imagePath).into(holder.mImageView);

    holder.mNewsTextView.setText(mNews.get(position).getNews());
    holder.mTimeStampTextView.setText(timeConverter(mNews.get(position).getTime()));
}

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

//    NewsHolder class that extends the ViewHolder
public static class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private ImageView mImageView;
    private TextView mNewsTextView;
    private TextView mTimeStampTextView;

    //   Setting the views
    public NewsHolder(View itemView) {
        super(itemView);
        mImageView = (ImageView) itemView.findViewById(R.id.simple_imageView);
        mNewsTextView = (TextView) itemView.findViewById(R.id.news_tv);
        mTimeStampTextView = (TextView) itemView.findViewById(R.id.time_tv);
    }

    @Override
    public void onClick(View view) {
        clickListener.onItemClick(getAdapterPosition(), view);
    }
}

public void setOnItemClickListener(ClickListener listener) {
    NewsAdapter.clickListener = listener;
}

public interface ClickListener {
    void onItemClick(int position, View v);
}

}

This is one of my ViewPager fragments:

public class TechFragment extends Fragment {
private SwipeRefreshLayout mSwipeRefreshLayout;
private TextView mErrorMessage;
private NewsAdapter mNewsAdapter;
ArrayList<News> news;
NetworkInfo info;
//  The Loader takes in a bundle
Bundle sourceBundle = new Bundle();

private final String LOG_TAG = MainActivity.class.getSimpleName();

private static final String TECH_NEWS_QUERY_URL = "query";
private static final String TECH_NEWS_SOURCE = "techcrunch";
private static final String TECH_SOURCE_CATEGORY = "latest";
private static final int TECH_NEWS_LOADER = 22;

private RecyclerView mRecyclerView;

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_news, container, false);
    mErrorMessage = (TextView) view.findViewById(R.id.tv_error_message);
    mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_main);
    mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefresh);

    getActivity().getSupportLoaderManager().initLoader(TECH_NEWS_LOADER, sourceBundle, new NewsDataLoader());

    mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            Log.v(LOG_TAG, "Refreshing");
            restartLoader();
            mSwipeRefreshLayout.setColorSchemeResources(
                    R.color.colorPrimary,
                    R.color.colorPrimaryDark);
        }
    });

    return view;
}

private boolean isConnected() {
    ConnectivityManager cm = (ConnectivityManager) getActivity()
            .getSystemService(CONNECTIVITY_SERVICE);

    info = cm.getActiveNetworkInfo();

    return info != null && info.isConnectedOrConnecting();
}

private int anyRandomInt(Random random) {
    return random.nextInt();
}

private void restartLoader() {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            URL techNewsUrl = NetworkUtils.buildUrl(TECH_NEWS_SOURCE, TECH_SOURCE_CATEGORY);
            sourceBundle.putString(TECH_NEWS_QUERY_URL, techNewsUrl.toString());

            Random random = new Random();
            int uniqueId = anyRandomInt(random); //Generates a new ID for each loader call;

            LoaderManager loaderManager = getActivity().getSupportLoaderManager();

            if (loaderManager.getLoader(TECH_NEWS_LOADER) == null) {
                loaderManager.initLoader(uniqueId, sourceBundle, new NewsDataLoader());
            } else {
                loaderManager.restartLoader(TECH_NEWS_LOADER, sourceBundle, new
                        NewsDataLoader());
            }
        }
    }, 5000);
    mSwipeRefreshLayout.setRefreshing(false);
    Log.v(LOG_TAG, "Finished refreshing");
}

private void showErrorScreen() {
    mErrorMessage.setVisibility(View.VISIBLE);
    mRecyclerView.setVisibility(View.INVISIBLE);
    mErrorMessage.setText(getString(R.string.internet_error));
}

public class NewsDataLoader implements LoaderManager.LoaderCallbacks<ArrayList<News>> {
    @Override
    public Loader<ArrayList<News>> onCreateLoader(int id, final Bundle args) {
        if (isConnected()) {
            mErrorMessage.setVisibility(View.INVISIBLE);
            mRecyclerView.setVisibility(View.VISIBLE);
            return new AsyncTaskLoader<ArrayList<News>>(getActivity()) {
                ArrayList<News> mNewsData;

                @Override
                protected void onStartLoading() {
                    super.onStartLoading();
                    if (mNewsData != null) {
                        deliverResult(mNewsData);
                    } else {
                        forceLoad();
                        mSwipeRefreshLayout.setRefreshing(true);
                    }
                }

                @Override
                public ArrayList<News> loadInBackground() {
                    try {
                        ArrayList<News> news = NetworkUtils.parseJSON(TECH_NEWS_SOURCE, TECH_SOURCE_CATEGORY);
                        return news;
                    } catch (IOException e) {
                        e.printStackTrace();
                        return null;
                    }
                }

                public void deliverResult(ArrayList<News> data) {
                    mNewsData = data;
                    super.deliverResult(data);
                }
            };
        } else {
            showErrorScreen();
            return null;
        }
    }

    @Override
    public void onLoadFinished(Loader<ArrayList<News>> loader, final ArrayList<News> data) {
        mSwipeRefreshLayout.setRefreshing(false);
        if (null == data) {
            showErrorScreen();
        } else {
            mErrorMessage.setVisibility(View.INVISIBLE);
            mRecyclerView.setVisibility(View.VISIBLE);
            if (news != null) {
                news.clear();
                news.addAll(data);
                mNewsAdapter = new NewsAdapter(news);
                mRecyclerView.setAdapter(mNewsAdapter);
                mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
                mNewsAdapter.notifyDataSetChanged();
            } else {
                news = data;
            }
        }
        mNewsAdapter.setOnItemClickListener(new NewsAdapter.ClickListener() {
            @Override
            public void onItemClick(int position, View v) {
                News currentNews = news.get(position);

                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentNews.getUrl()));
                if (intent.resolveActivity(getActivity().getPackageManager()) != null){
                    startActivity(intent);
                }
            }
        });
    }


    @Override
    public void onLoaderReset(Loader<ArrayList<News>> loader) {
    }

}

}

And this is my error:

06-13 12:11:38.667 3890-3890/com.ire.blogbot E/AndroidRuntime: FATAL EXCEPTION: main
                                                           Process: com.ire.blogbot, PID: 3890
                                                           java.lang.NullPointerException: Attempt to invoke virtual method 'void com.ire.blogbot.adapter.NewsAdapter.setOnItemClickListener(com.ire.blogbot.adapter.NewsAdapter$ClickListener)' on a null object reference
                                                               at com.ire.blogbot.fragments.TechFragment$NewsDataLoader.onLoadFinished(TechFragment.java:192)
                                                               at com.ire.blogbot.fragments.TechFragment$NewsDataLoader.onLoadFinished(TechFragment.java:131)
                                                               at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:476)
                                                               at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:444)
                                                               at android.support.v4.content.Loader.deliverResult(Loader.java:126)
                                                               at com.ire.blogbot.fragments.TechFragment$NewsDataLoader$1.deliverResult(TechFragment.java:164)
                                                               at com.ire.blogbot.fragments.TechFragment$NewsDataLoader$1.deliverResult(TechFragment.java:137)
                                                               at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:252)
                                                               at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:80)
                                                               at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:485)
                                                               at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:502)
                                                               at android.os.Handler.dispatchMessage(Handler.java:102)
                                                               at android.os.Looper.loop(Looper.java:154)
                                                               at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Move

mNewsAdapter.setOnItemClickListener(new NewsAdapter.ClickListener() {
            @Override
            public void onItemClick(int position, View v) {
                News currentNews = news.get(position);

                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentNews.getUrl()));
                if (intent.resolveActivity(getActivity().getPackageManager()) != null){
                    startActivity(intent);
                }
            }
        });

after

mNewsAdapter = new NewsAdapter(news);

Try this code, it is working

recyclerView.addOnItemTouchListener(
            new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
                @Override public void onItemClick(View view, int position) {

                   // on click 
                }
            })
    );

RecyclerItemClickListener Class

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {

private OnItemClickListener mListener;

public interface OnItemClickListener {
    public void onItemClick(View view, int position);
}

GestureDetector mGestureDetector;

public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
    mListener = listener;
    mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }
    });
}

@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
    View childView = view.findChildViewUnder(e.getX(), e.getY());
    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
        mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
    }
    return false;
}

@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}}

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