Lưu trạng thái fragment trên android

Chào mọi người,
Mình muốn hỏi cách lưu 1 trạng thái fragment trên android giống như zalo chuyển qua các tab mà nó chỉ load lần đầu thôi.
Ai có cao kiến gì không.Mình đã thử search google mà không ra.
Xin cảm ơn

2 Likes

Ở chỗ xử lý chuyển fragment mình toàn dùng replace nên nó không lưu lại được bạn ạ.Vậy có cách nào chuyển fragment mà vẫn lưu được không

Bạn có thể post code lên được không ? :slight_smile:

 if (id == R.id.nav_home) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_switch, new Home(), "home");
        fragmentTransaction.commit();
    } else if (id == R.id.nav_info) {

    } else if (id == R.id.nav_category) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_switch, new Category(), "category");
        fragmentTransaction.commit();

    }

Đây là hàm xử lý khi ở activity main mình chuyển qua lại giữa các fragmment còn mình lúc trước cũng làm theo cách của bạn ở link trên nó chỉ lưu trạng thái xoay màn hình thôi :slight_smile:

Bạn cho mình xem luôn class Fragment luôn đi

Đây là hàm lưu của mình

@Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        position = viewPager.getCurrentItem();
        outState.putInt("page", pageindex);
        outState.putInt("position", position);
        outState.putParcelableArrayList("list_image",listPage);
    }

và đây là hàm restore

 @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null) {
            // Restore last state

            position = savedInstanceState.getInt("position");
            pageindex = savedInstanceState.getInt("page");
            listPage = savedInstanceState.getParcelableArrayList("list_image");
            FullScreenImageAdapter adapter = new FullScreenImageAdapter(getActivity(), listPage);
            viewPager.setAdapter(adapter);
            viewPager.setCurrentItem(position);
            ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Mới cập nhật (Page " + pageindex + ")");
        } else {
            position = 0;
            APIInterface apiService = ApiClient.getClient().create(APIInterface.class);
            Call<Result> call = apiService.getPages(pageindex);
            PagesAsyncTask pagesAsyncTask = new PagesAsyncTask(getActivity(), frameLayout);
            pagesAsyncTask.execute(call);
        }
    }

Khi bạn replace fragment A với fragment B thì FragmentManager sẽ xóa fragment A đi, rồi add fragment B vào -> Dẫn đến khi bạn nhấn nút Back nó sẽ tạo mới fragment A.
Solution: Trước khi replace, bạn nên dùng method addToBackStack của FragmentTransaction để add fragment A vào back stack (stack chứa các fragment hiển thị khi người dùng bấm nút back).

Còn việc lưu state của fragment, đúng như bạn nói, onSaveInstance() chỉ được gọi khi thay đổi configure (xoay màn hình,…) nên theo mình những cái gì cần lưu lại thì bạn nên gán vào biến instance của fragment A bởi vì khi bạn bấm nút back thì FragmentManager sẽ pop cái thằng Fragment nằm trên top của back stack, lúc này fragment vẫn được giữ nguyên (biến instance vẫn được giữ), ngoại trừ phải render view lại thôi.

Bạn cứ thử đi :slight_smile:

2 Likes

Mình cũng đã thử addToBackStack (null) rồi.Nhưng vẫn không hiệu quả bạn ạ :frowning:

Bạn gán null cho nó thì làm sao nó biết là fragment A hay ko ? -.-
Bạn phải gán tag của fragment A cho parameter để FragmentManager nhận diện

1 Like

Thông thường thì đặt fragment là biến toàn cục và khởi tạo ở phương thức OnCreate() :slight_smile:

OOP không có khái niệm là biến toàn cục nha bạn :slight_smile:. Chỉ có biến static hoặc là biến instance thôi

1 Like

Bạn bắt bẻ quá, biến toàn cục là các field trong class đó :joy: Đang nói trong 1 Activity mà

Mình mới thử xong cũng vậy bạn ạ.Tại mình nghĩ nó chỉ có tác dụng ở lúc pop fragment ra thôi.Chứ mình muốn khi nhấn vao 1 button nào đó trên activity nó vẫn giữ được dữ liệu

Đặt các fragment là biến toàn cục trong Activity, khởi tạo tại OnCreate(), khi replace fragment phải lưu lại state của nó bằng cách sử dụng Bundle :slight_smile:
Nay đang rảnh, ai hỏi về Android, mình giúp cho :joy:

Bạn cho mình 1 ví dụ được không.Mình mới qua mảng này nên hơi khó hiểu :frowning:

if (id == R.id.nav_home) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_switch, new Home(), "home");
        fragmentTransaction.commit();
    } else if (id == R.id.nav_info) {

    } else if (id == R.id.nav_category) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_switch, new Category(), "category");
        fragmentTransaction.commit();

    }

Sài thế này là sai rồi, các khởi tạo Category, Home chỉ nên tạo 1 lần thôi, bạn tạo như này là mất hết dữ liệu…
Khi replace 1 fragment nào đó, phải lưu state nó lại trong phương thức OnPause của Fragment, và khi nào replace lại fragment đó thì gọi lại…

Mình để khởi tạo 1 lần vẫn vậy bạn ạ.Sau mình dùng hàm public void onSaveInstanceState(Bundle outState) để lưu lại vẫn bị.

   if (id == R.id.nav_home) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_switch, home, "home");
        fragmentTransaction.commit();
    } else if (id == R.id.nav_info) {

    } else if (id == R.id.nav_category) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_switch, category, "category");
        fragmentTransaction.commit();

    }

Sau khi sửa lại thế này phải không ạ

Bạn up hết code mình xem thử :grinning:
Lưu state và khi Onstart fragment phải check xem coi có state đã lưu ko, nếu có thì lấy lên

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?