getActivity() returns null in Fragment function

后端 未结 15 1703
别那么骄傲
别那么骄傲 2020-11-22 07:28

I have a fragment (F1) with a public method like this

public void asd() {
    if (getActivity() == null) {
        Log.d(\"yes\",\"it is null\");
    }
}


        
相关标签:
15条回答
  • 2020-11-22 08:12

    PJL is right. I have used his suggestion and this is what i have done:

    1. defined global variables for fragment:

      private final Object attachingActivityLock = new Object();

      private boolean syncVariable = false;

    2. implemented

    @Override
    public void onAttach(Activity activity) {
      super.onAttach(activity);
      synchronized (attachingActivityLock) {
          syncVariable = true;
          attachingActivityLock.notifyAll();
      }
    }
    

    3 . I wrapped up my function, where I need to call getActivity(), in thread, because if it would run on main thread, i would block the thread with the step 4. and onAttach() would never be called.

        Thread processImage = new Thread(new Runnable() {
    
            @Override
            public void run() {
                processImage();
            }
        });
        processImage.start();
    

    4 . in my function where I need to call getActivity(), I use this (before the call getActivity())

        synchronized (attachingActivityLock) {
            while(!syncVariable){
                try {
                    attachingActivityLock.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    

    If you have some UI updates, remember to run them on UI thread. I need to update ImgeView so I did:

    image.post(new Runnable() {
    
        @Override
        public void run() {
            image.setImageBitmap(imageToShow);
        }
    });
    
    0 讨论(0)
  • 2020-11-22 08:14

    You can using onAttach or if you do not want to put onAttach everywhere then you can put a method that returns ApplicationContext on the main App class :

    public class App {
        ...  
        private static Context context;
    
        @Override
        public void onCreate() {
            super.onCreate();
            context = this;
        }
    
        public static Context getContext() {
            return context;
        }
        ...
    }
    

    After that you can re-use it everywhere in all over your project, like this :

    App.getContext().getString(id)
    

    Please let me know if this does not work for you.

    0 讨论(0)
  • 2020-11-22 08:18

    The best to get rid of this is to keep activity reference when onAttach is called and use the activity reference wherever needed, for e.g.

    @Override
    public void onAttach(Context context) {
        super.onAttach(activity);
        mContext = context;
    }
    
    @Override
    public void onDetach() {
        super.onDetach();
        mContext = null;
    }
    
    0 讨论(0)
  • 2020-11-22 08:18

    The order in which the callbacks are called after commit():

    1. Whatever method you call manually right after commit()
    2. onAttach()
    3. onCreateView()
    4. onActivityCreated()

    I needed to do some work that involved some Views, so onAttach() didn't work for me; it crashed. So I moved part of my code that was setting some params inside a method called right after commit() (1.), then the other part of the code that handled view inside onCreateView() (3.).

    0 讨论(0)
  • 2020-11-22 08:18

    I am using OkHttp and I just faced this issue.


    For the first part @thucnguyen was on the right track.

    This happened when you call getActivity() in another thread that finished after the fragment has been removed. The typical case is calling getActivity() (ex. for a Toast) when an HTTP request finished (in onResponse for example).

    Some HTTP calls were being executed even after the activity had been closed (because it can take a while for an HTTP request to be completed). I then, through the HttpCallback tried to update some Fragment fields and got a null exception when trying to getActivity().

    http.newCall(request).enqueue(new Callback(...
      onResponse(Call call, Response response) {
        ...
        getActivity().runOnUiThread(...) // <-- getActivity() was null when it had been destroyed already
    

    IMO the solution is to prevent callbacks to occur when the fragment is no longer alive anymore (and that's not just with Okhttp).

    The fix: Prevention.

    If you have a look at the fragment lifecycle (more info here), you'll notice that there's onAttach(Context context) and onDetach() methods. These get called after the Fragment belongs to an activity and just before stop being so respectively.

    That means that we can prevent that callback to happen by controlling it in the onDetach method.

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    
        // Initialize HTTP we're going to use later.
        http = new OkHttpClient.Builder().build();
    }
    
    @Override
    public void onDetach() {
        super.onDetach();
    
        // We don't want to receive any more information about the current HTTP calls after this point.
        // With Okhttp we can simply cancel the on-going ones (credits to https://github.com/square/okhttp/issues/2205#issuecomment-169363942).
        for (Call call : http.dispatcher().queuedCalls()) {
            call.cancel();
        }
        for (Call call : http.dispatcher().runningCalls()) {
            call.cancel();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:18

    Call getActivity() method inside the onActivityCreated()

    0 讨论(0)
提交回复
热议问题