Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
232 views
in Technique[技术] by (71.8m points)

android - Why getContext() in fragment sometimes returns null?

Why getContext() sometimes returns null? I pass context to LastNewsRVAdapter.java as an argument. But LayoutInflater.from(context) sometimes crashes. I'm getting a few crash reports on play console. Below is crash report.

java.lang.NullPointerException
com.example.adapters.LastNewsRVAdapter.<init>

java.lang.NullPointerException: 
at android.view.LayoutInflater.from (LayoutInflater.java:211)
at com.example.adapters.LastNewsRVAdapter.<init> (LastNewsRVAdapter.java)
at com.example.fragments.MainFragment$2.onFailure (MainFragment.java)
or                     .onResponse (MainFragment.java)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run 
(ExecutorCallAdapterFactory.java)
at android.os.Handler.handleCallback (Handler.java:808)
at android.os.Handler.dispatchMessage (Handler.java:103)
at android.os.Looper.loop (Looper.java:193)
at android.app.ActivityThread.main (ActivityThread.java:5299)
at java.lang.reflect.Method.invokeNative (Method.java)
at java.lang.reflect.Method.invoke (Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run 
(ZygoteInit.java:825)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:641)
at dalvik.system.NativeStart.main (NativeStart.java)

This is LastNewsRVAdapter.java constructor.

public LastNewsRVAdapter(Context context, List<LatestNewsData> 
    latestNewsDataList, FirstPageSideBanner sideBanner) {
    this.context = context;
    this.latestNewsDataList = latestNewsDataList;
    inflater = LayoutInflater.from(context);
    this.sideBanner = sideBanner;
}

This is the code onCreateView inside Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment

    final View view = inflater.inflate(R.layout.fragment_main_sonku_kabar, container, false);
    tvSonkuKabar = view.findViewById(R.id.textview_sonku_kabar_main);
    tvNegizgiKabar = view.findViewById(R.id.textview_negizgi_kabar_main);
    refresh(view);

    final SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.mainRefreshSonkuKabar);
    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            refresh(view);
            swipeRefreshLayout.setRefreshing(false);
        }
    });
    setHasOptionsMenu(true);
    return view;
}

This is refresh method inside Fragment

private void refresh(final View view) {
    sideBanner = new FirstPageSideBanner();

    final RecyclerView rvLatestNews = (RecyclerView) view.findViewById(R.id.recViewLastNews);
    rvLatestNews.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
    rvLatestNews.setNestedScrollingEnabled(false);
    App.getApiService().getLatestNews().enqueue(new Callback<LatestNews>() {
        @Override
        public void onResponse(Call<LatestNews> call, Response<LatestNews> response) {
            if (response.isSuccessful() && response.body().isSuccessfull()){
                adapter = new LastNewsRVAdapter(getContext(), response.body().getData(), sideBanner);
                rvLatestNews.setAdapter(adapter);
                tvSonkuKabar.setVisibility(View.VISIBLE);
            }
        }

        @Override
        public void onFailure(Call<LatestNews> call, Throwable t) {

        }
    });
question from:https://stackoverflow.com/questions/47987649/why-getcontext-in-fragment-sometimes-returns-null

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all, as you can see on this link, the method onCreateView() inside the fragment's lifecycle comes after onAttach(), so you should have already a context at that point. You may wonder, why does getContext() return null then? the problem lies on where you are creating your adapter:

App.getApiService().getLatestNews().enqueue(new Callback<LatestNews>() {
        @Override
        public void onResponse(Call<LatestNews> call, Response<LatestNews> response) {
            if (response.isSuccessful() && response.body().isSuccessfull()){
                adapter = new LastNewsRVAdapter(getContext(), response.body().getData(), sideBanner);
                rvLatestNews.setAdapter(adapter);
                tvSonkuKabar.setVisibility(View.VISIBLE);
            }
        }

        @Override
        public void onFailure(Call<LatestNews> call, Throwable t) {

        }
    });

Though you are specifying a callback in onCreateView(), that does not mean the code inside that callback will run at that point. It will run and create the adapter after the network call is done. With that in mind, your callback may run after that point in the lifecycle of the fragment. What I mean is that the user can enter that screen (fragment) and go to another fragment or return to the previous one before the network request finishes (and the callback runs). If that happens, then getContext() could return null if the user leaves the fragment (onDetach() may have been called).

Besides, you can have memory leaks also, in case the activity is destroyed before your network request finishes. So you have two issues there.

My suggestions to solve those issues are:

  1. in order to avoid the null pointer exception and the memory leak, you should cancel the network request when the onDestroyView() inside the fragment is being called (retrofit returns an object that can cancel the request: link).

  2. Another option that will prevent the null pointer exception is to move the creation of the adapter LastNewsRVAdapter outside the callback and keep a reference to it in the fragment. Then, use that reference inside the callback to update the content of the adapter: link


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...