屏幕旋转时如何在Recyclerview中保存状态数据

时间:2019-08-11 04:38:12

标签: android android-activity fragment screen-orientation state-management

我使用android java编程语言创建了一个Movie应用程序,使用API​​从TMDB提取的数据,一切都很好,并且按我的预期工作,但是问题是当屏幕旋转时,一次又一次地重新加载数据,我正在跟踪该网站上的一些教程,但仍然无法正常工作。

我正在跟踪以下链接:How to save an Android Activity state using save instance state?,但是我无法弄清楚本教程要针对我的情况实施

// this is my Movie Fragment
package com.ogi.layarkacamobile.fragment;


import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;

import com.ogi.layarkacamobile.MainActivity;
import com.ogi.layarkacamobile.R;
import com.ogi.layarkacamobile.adapter.MoviesAdapter;
import com.ogi.layarkacamobile.api.Client;
import com.ogi.layarkacamobile.api.Service;
import com.ogi.layarkacamobile.model.movie.MovieData;
import com.ogi.layarkacamobile.model.movie.MoviesResponse;
import com.ogi.layarkacamobile.util.PaginationScrollListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * A simple {@link Fragment} subclass.
 */
public class MoviesFragment extends Fragment {
    private static final String TAG = "MoviesFragment";

    RecyclerView rvMoviesList;
    ProgressBar pbMovies;
    MoviesAdapter moviesAdapter;
    LinearLayoutManager linearLayoutManager;

    private static final int PAGE_START = 1;
    private boolean isLoading = false;
    private boolean isLastPage = false;

    private int TOTAL_PAGES = 10;
    private int currentPage = PAGE_START;

    private Service movieService;

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


    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View layout = LayoutInflater.from(getContext()).inflate(R.layout.fragment_movies, container, false);
        rvMoviesList = layout.findViewById(R.id.rv_movies_id);
        pbMovies = layout.findViewById(R.id.pb_movies_id);
        moviesAdapter = new MoviesAdapter(getContext());

        linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
        rvMoviesList.setLayoutManager(linearLayoutManager);

        rvMoviesList.setItemAnimator(new DefaultItemAnimator());
        rvMoviesList.setAdapter(moviesAdapter);

        rvMoviesList.addOnScrollListener(new PaginationScrollListener(linearLayoutManager) {
            @Override
            protected void loadMoreItems() {
                isLoading = true;
                currentPage += 1;

                // mocking network delay for API  call
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        loadNextPage();
                    }
                }, 1000);
            }

            @Override
            public int getTotalPageCount() {
                return TOTAL_PAGES;
            }

            @Override
            public boolean isLastPage() {
                return isLastPage;
            }

            @Override
            public boolean isLoading() {
                return isLoading;
            }
        });

        // init service and load data
        movieService = Client.getClient().create(Service.class);

        loadFirstPage();

        return layout;
    }

    private void loadFirstPage() {
        Log.d(TAG, "LoadFirstPage");

        callPopularMovieApi()
                .enqueue(new Callback<MoviesResponse>() {
                    @Override
                    public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response) {
                        // Got data send into adapter
                        List<MovieData> results = fetchResults(response);
                        pbMovies.setVisibility(View.GONE);
                        moviesAdapter.addAll(results);

                        if (currentPage <= TOTAL_PAGES) moviesAdapter.addLoadingFooter();
                        else isLastPage = true;
                    }

                    @Override
                    public void onFailure(Call<MoviesResponse> call, Throwable t) {
                        t.printStackTrace();
                    }
                });

    }

    private List<MovieData> fetchResults(Response<MoviesResponse> response) {
        MoviesResponse popularMovies = response.body();
        return popularMovies.getResults();
    }

    private void loadNextPage() {
        Log.d(TAG, "loadNextPage "+ currentPage);
        callPopularMovieApi()
                .enqueue(new Callback<MoviesResponse>() {
                    @Override
                    public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response) {
                        moviesAdapter.removeLoadingFooter();
                        isLoading = false;

                        List<MovieData> results = fetchResults(response);
                        moviesAdapter.addAll(results);

                        if (currentPage != TOTAL_PAGES)moviesAdapter.addLoadingFooter();
                        else isLastPage = true;
                    }

                    @Override
                    public void onFailure(Call<MoviesResponse> call, Throwable t) {
                        t.printStackTrace();
                    }
                });
    }

    private Call<MoviesResponse> callPopularMovieApi() {
        return  movieService.getPopularMovies("f6602517b834e9ce06a48548f949e397", currentPage);
    }

}

这是我的MainActivity

package com.ogi.layarkacamobile;

import android.content.Intent;
import android.provider.Settings;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

import com.ogi.layarkacamobile.adapter.ViewPagerAdapter;
import com.ogi.layarkacamobile.fragment.MoviesFragment;
import com.ogi.layarkacamobile.fragment.TvShowsFragment;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ViewPager viewPager = findViewById(R.id.viewpager);
            setupViewPager(viewPager);

        TabLayout tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new MoviesFragment(), getResources().getString(R.string.movies_label));
        adapter.addFragment(new TvShowsFragment(), getResources().getString(R.string.tv_shows_label));
        viewPager.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.language_setting) {
            Intent mIntent = new Intent(Settings.ACTION_LOCALE_SETTINGS);
            startActivity(mIntent);
        }
        return super.onOptionsItemSelected(item);
    }
}

我正在尝试有关类似问题的建议,但没有一个可行,因为我不知道如何在我的情况下实施该问题,非常感谢您

2 个答案:

答案 0 :(得分:1)

片段:

您正在使用片段。因此,防止方向发生破坏时可以使用setRetainInstance(true)

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment when activity is re-initialized
        setRetainInstance(true);
    } 

活动:

发生方向改变时,android重新启动正在运行的Activity(调用onDestroy(),然后调用onCreate())。 如果要处理内部活动,则不能在清单文件中使用:进行特定活动。

对于API 12及以下版本:

android:configChanges="orientation"

如果您定位的是API 13或更高版本

android:configChanges="orientation|screenSize"

更新:在方向更改时保存片段状态

如果要在活动内部使用onSaveInstanceState保存片段状态,则可以使用putFragment
在您的活动中,onSaveInstanceState如下所示:

@Override
protected void onSaveInstanceState(Bundle outState) {
   getFragmentManager().putFragment(outState, MyFragment.TAG, mMyFragment);
}

要在活动重启后获取片段状态,可以使用getFragment方法。

@Override
protected void onRestoreInstanceState(Bundle inState) {


   FragmentTransaction transaction =getFragmentManager().beginTransaction();

   if (inState != null) {
      mMyFragment = (MyFragment) getFragmentManager().getFragment(inState, MyFragment.TAG);
   } else {
      mMyFragment = new MyFragment();
      transaction.add(R.id.fragment, mMyFragment, MyFragment.TAG);
      transaction.commit();
   }

}

答案 1 :(得分:0)

使用LiveData。旋转设备时,它将缓存您的Recyclerview数据并从内部缓存中重新加载数据。