getActivity () zwraca null w funkcji Fragment

Mam fragment (F1) z publiczną metodą taką jak Ta

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

I tak, kiedy ją wywołuję( z aktywności), to jest null...

FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();

To musi być coś, co robię bardzo źle, ale nie wiem, co to jest

Author: josemigallas, 2011-06-02

13 answers

commit planuje transakcję, tzn. nie odbywa się ona od razu, ale jest zaplanowana jako praca nad głównym wątkiem następnym razem, gdy główny wątek jest gotowy.

Proponuję dodać

onAttach(Activity activity)

Metoda do twojego {[2] } i umieszczenie na nim punktu przerwania i sprawdzenie, kiedy jest wywołana względem Twojego połączenia do asd(). Zobaczysz, że jest wywoływana po metodzie, w której wykonujesz wywołanie asd() exits. Wywołanie onAttach jest tam, gdzie Fragment jest dołączone do jego aktywności i od tego momentu getActivity() zwróci wartość non-null (nb jest również wywołanie onDetach()).

 148
Author: PJL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-23 05:31:50

Najlepszym sposobem pozbycia się tego jest zachowanie odniesienia do aktywności podczas wywoływania onAttach i użycie odniesienia do aktywności wszędzie tam, gdzie jest to potrzebne, na przykład

@Override
public void onAttach(Context context) {
    super.onAttach(activity);
    mContext = context;
}

@Override
public void onDetach() {
    super.onDetach();
    mContext = null;
}
 76
Author: Pawan Maheshwari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 11:22:17

Stało się to, gdy wywołujesz getActivity() w innym wątku, który zakończył się po usunięciu fragmentu. Typowym przypadkiem jest wywołanie getActivity() (ex. dla Toast), gdy żądanie HTTP zostało zakończone (na przykład w onResponse).

Aby tego uniknąć, możesz zdefiniować nazwę pola mActivity i użyć jej zamiast getActivity(). Pole to można zainicjować w metodzie OnAttach() fragmentu w następujący sposób:

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
    mActivity = activity;
}

W moich projektach zazwyczaj definiuję klasę bazową dla wszystkich moich fragmentów za pomocą tego cecha:

public abstract class BaseFragment extends Fragment {

    protected FragmentActivity mActivity;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mActivity = (FragmentActivity) activity;
    }
}

Happy coding,

 60
Author: thucnguyen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-28 16:05:22

Od poziomu API Androida 23, onAttach (aktywność) została wycofana. Musisz użyć OnAttach (kontekst kontekstu). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)

Aktywność jest kontekstem, więc jeśli możesz po prostu sprawdzić, czy kontekst jest aktywnością i rzucić go w razie potrzeby.

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity a;

    if (context instanceof Activity){
        a=(Activity) context;
    }

}
 16
Author: Sachin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-13 19:48:28

PJL ma rację. Użyłem jego sugestii i to właśnie zrobiłem:

  1. Zdefiniowane zmienne globalne dla fragmentu:

    private final Object attachingActivityLock = new Object();

    private boolean syncVariable = false;

  2. Zaimplementowane

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

3 . Zamknąłem swoją funkcję, gdzie muszę wywołać getActivity (), w wątku, ponieważ gdyby działała na głównym wątku, zablokowałbym wątek za pomocą kroku 4. i onAttach () nigdy nie zostanie wywołane.

    Thread processImage = new Thread(new Runnable() {

        @Override
        public void run() {
            processImage();
        }
    });
    processImage.start();

4 . w mojej funkcji, gdzie potrzebuję aby wywołać getActivity (), używam tego (przed wywołaniem getActivity ())

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

jeśli masz jakieś aktualizacje interfejsu, pamiętaj, aby uruchomić je w wątku interfejsu. Muszę zaktualizować ImgeView więc zrobiłem:

image.post(new Runnable() {

    @Override
    public void run() {
        image.setImageBitmap(imageToShow);
    }
});
 9
Author: zajac.m2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-17 02:21:07

Kolejność wywoływania wywołań zwrotnych po commit ():

  1. niezależnie od metody wywołanej ręcznie zaraz po commit ()
  2. onAttach ()
  3. onCreateView ()
  4. onActivityCreated ()

Musiałem wykonać jakąś pracę, która wiązała się z pewnymi widokami, więc onAttach() nie zadziałało dla mnie; zawiesiło się. Przeniosłem więc część mojego kodu, który ustawiał params wewnątrz metody nazwanej zaraz po commit () (1.), następnie druga część kodu, która obsługiwała widok wewnątrz onCreateView () (3.).

 7
Author: Bogdan Zurac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-01 14:06:40

Inne odpowiedzi sugerujące utrzymywanie odniesienia do aktywności w onAttach sugerują tylko bandaid do prawdziwego problemu. Gdy getActivity zwraca null oznacza to, że Fragment nie jest dołączony do aktywności. Najczęściej dzieje się tak, gdy czynność odeszła z powodu obrotu lub czynności jest zakończona, ale Fragment ma jakiś rodzaj słuchacza zwrotnego. Kiedy słuchacz zostanie wezwany, jeśli musisz coś zrobić z aktywnością, ale aktywność nie ma tam niewiele możesz zrobić. W kodzie należy po prostu sprawdzić getActivity() != null, a jeśli go nie ma, to nic nie rób. Jeśli zachowasz odniesienie do działania, które zniknęło, zapobiegasz zbieraniu śmieci. Wszelkie elementy interfejsu użytkownika, które możesz spróbować zrobić, nie będą widoczne dla użytkownika. Mogę sobie wyobrazić sytuacje, w których w słuchaczu wywołania zwrotnego możesz chcieć mieć kontekst dla czegoś, co nie jest związane z interfejsem użytkownika, w tych przypadkach prawdopodobnie bardziej sensowne jest uzyskanie kontekstu aplikacji. Zauważ, że jedynym powodem, dla którego sztuczka onAttach nie jest wielkim wyciekiem pamięci, jest to, że zwykle po wykonaniu wywołania zwrotnego nie będzie już potrzebna i może być zbierana wraz z fragmentem, całym jego widokiem i kontekstem aktywności. Jeśli setRetainInstance(true) istnieje większa szansa na wyciek pamięci, ponieważ pole aktywności również zostanie zachowane, ale po rotacji może to być poprzednia aktywność, a nie bieżąca.

 5
Author: miguel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 17:33:18

Wykonaj następujące czynności. Myślę, że to ci pomoże.

private boolean isVisibleToUser = false;
private boolean isExecutedOnce = false;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_my, container, false);
    if (isVisibleToUser && !isExecutedOnce) {
        executeWithActivity(getActivity());
    }
    return root;
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    this.isVisibleToUser = isVisibleToUser;
    if (isVisibleToUser && getActivity()!=null) {
        isExecutedOnce =true;
        executeWithActivity(getActivity());
    }
}


private void executeWithActivity(Activity activity){
    //Do what you have to do when page is loaded with activity

}
 1
Author: Vinil Chandran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-21 13:04:39

Gdzie nazywa się tę funkcję? Jeśli wywołasz go w konstruktorze Fragment, zwróci null.

Po prostu wywołaj getActivity() gdy Metoda onCreateView() jest wykonywana.

 1
Author: Phạm Lam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 10:40:07

Używam OkHttp i właśnie stanąłem przed tym problemem.


W pierwszej części @thucnguyen był na dobrej drodze.

Stało się to, gdy wywołujesz getActivity () w innym wątku, który zakończył się po usunięciu fragmentu. Typowym przypadkiem jest wywołanie getActivity () (ex. na Toast) po zakończeniu żądania HTTP (na przykład w onResponse).

Niektóre wywołania HTTP były wykonywane nawet po aktywności closed (ponieważ wypełnienie żądania HTTP może chwilę potrwać). Następnie, poprzez HttpCallback próbowałem zaktualizować niektóre pola Fragment i dostałem wyjątek null podczas próby getActivity().

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

IMO rozwiązaniem jest zapobieganie wystąpieniu wywołań zwrotnych, gdy fragment nie jest już żywy (i to nie tylko z Okhttp).

Poprawka: zapobieganie.

Jeśli spojrzeć na fragment cyklu życia (więcej informacji tutaj ), będziesz zauważ, że istnieją metody onAttach(Context context) i onDetach(). Są one wywoływane po tym, jak Fragment należy do czynności i tuż przed przestać być odpowiednio.

Oznacza to, że możemy zapobiec wywołaniu zwrotnemu, kontrolując go metodą onDetach.

@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();
    }
}
 1
Author: zurfyx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 16:20:21

Ci, którzy nadal mają problem z onAttach (aktywność), jego po prostu zmienił się kontekst-

    @Override
public void onAttach(Context context) {
    super.onAttach(context);
    this.context = context;
}

W większości przypadków zapisanie kontekstu wystarczy - na przykład, jeśli chcesz wykonać getResources (), możesz to zrobić bezpośrednio z kontekstu. Jeśli nadal musisz wprowadzić kontekst do swojej aktywności, zrób to -

 @Override
public void onAttach(Context context) {
    super.onAttach(context);
    mActivity a; //Your activity class - will probably be a global var.
    if (context instanceof mActivity){
        a=(mActivity) context;
    }
}

Zgodnie z sugestią user1868713.

 0
Author: Shai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-26 10:30:58

Możesz użyć onAttach lub jeśli nie chcesz umieścić OnAttach wszędzie, możesz umieścić metodę, która zwraca ApplicationContext na głównej klasie aplikacji:

public class App {
    ...  
    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;
    }

    public static Context getContext() {
        return context;
    }
    ...
}

Następnie możesz ponownie użyć go wszędzie w całym projekcie, w następujący sposób:

App.getContext().getString(id)

Proszę dać mi znać, jeśli to nie działa dla Ciebie.

 0
Author: surga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 01:59:31

Najlepszy i solidny sposób:

FragmentActivity activity = (FragmentActivity) getActivity();

activity.finish();
 -5
Author: Farhad Mammadli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 10:48:16