热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

无法在屏幕旋转时保持RecyclerView位置

如何解决《无法在屏幕旋转时保持RecyclerView位置》经验,为你挑选了1个好方法。

我正在加载RecyclerView基于对Retrofit本地SQLite数据库的调用和存储的数据的。

屏幕旋转时,RecyclerView保持重置。此外,当我喜欢电影时(将电影添加到我的本地房间数据库中),在某些情况下,微调器无法与填充的数据对齐RecyclerView。下面是我的代码:

public class MainActivity extends AppCompatActivity {

private RecyclerView mMovieResults;
private MyAdapter mMovieResultsAdapter;
private String query;
private String mBaseURL;
private int lastFirstVisiblePosition;
//TODO: How is someone able to load my API Key if I am storing it


private ArrayList mMovieURLS;
private ArrayList mMovies;
private List mMovieResultsList;

private static final String SPINNER_SELECTION = "SPINNER_SELECTION";

private boolean mIsFavoriteSelected;

private AppDatabase mDb;

private Spinner mSpinner;

private SharedPreferences mPrefs;
private SharedPreferences.Editor mPrefsEditor;

private static Bundle mBundleRecyclerViewState;


private int saved_selection = -1;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.v("ONCREATE", "ONCREATE");
    if (savedInstanceState != null){
        saved_selection = savedInstanceState.getInt(SPINNER_SELECTION);
    }

    if (isOnline()) {
        setContentView(R.layout.activity_main);
        Stetho.initializeWithDefaults(this);
        mDb = AppDatabase.getInstance(getApplicationContext());
        mMovieResults = findViewById(R.id.main_recyclerview_image_results);
        GridLayoutManager glm = new GridLayoutManager(this, 3);
        glm.setOrientation(LinearLayoutManager.VERTICAL);
        mMovieResults.setLayoutManager(glm);
        mMovieURLS = new ArrayList<>();
        mMovies = new ArrayList<>();
        mMovieResultsList = new ArrayList<>();
        mMovieResultsAdapter = new MyAdapter(mMovieResultsList);
        mMovieResults.setAdapter(mMovieResultsAdapter);
        mDb = AppDatabase.getInstance(getApplicationContext());
        mPrefs = getSharedPreferences("prefs", MODE_PRIVATE);

        mPrefsEditor = mPrefs.edit();
        switch (saved_selection){
                case 0:
                    mBaseURL = "https://api.themoviedb.org/3/movie/popular/";
                    calltoRetrofit(mBaseURL);
                    break;
                case 1:
                    mBaseURL = "https://api.themoviedb.org/3/movie/top_rated/";
                    calltoRetrofit(mBaseURL);
                    break;
                case 2:
                    mIsFavoriteSelected = true;
                    mMovieURLS.clear();
                    retrieveMovies();
                    break;

                default:
                    mBaseURL = "https://api.themoviedb.org/3/movie/popular/";
                    break;
            }


    } else {
        setContentView(R.layout.activity_no_internet);
        return;
    }

}





@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.action_bar_spinner, menu);
    MenuItem item = menu.findItem(R.id.spinner);
    mSpinner = (Spinner) item.getActionView();
    if (isOnline()) {
        ArrayAdapter adapter = ArrayAdapter.createFromResource(getApplicationContext(), R.array.spiner_list_item_array, R.layout.custom_spinner);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mSpinner.setAdapter(adapter);
        if (saved_selection >= 0){
            mSpinner.setSelection(saved_selection);
        }
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView adapterView, View view, int i, long l) {
                mPrefsEditor.putInt(SPINNER_SELECTION, i);
                mPrefsEditor.commit();
                switch (i) {
                    case 0:
                        mBaseURL = "https://api.themoviedb.org/3/movie/popular/";
                        calltoRetrofit(mBaseURL);
                        break;
                    case 1:
                        mBaseURL = "https://api.themoviedb.org/3/movie/top_rated/";
                        calltoRetrofit(mBaseURL);
                        break;
                    case 2:
                        mIsFavoriteSelected = true;
                        mMovieURLS.clear();
                        retrieveMovies();
                        break;

                    default:
                        mBaseURL = "https://api.themoviedb.org/3/movie/popular/";
                        break;
                }


            }

            @Override
            public void onNothingSelected(AdapterView adapterView) {

            }
        });
        return true;
    } else {
        return true;
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putInt(SPINNER_SELECTION, mSpinner.getSelectedItemPosition());
    super.onSaveInstanceState(outState);
}



@Override
public boolean onOptionsItemSelected(MenuItem item) {
    super.onOptionsItemSelected(item);
    int x = item.getItemId();
    Log.v("OPTIONS_ID", String.valueOf(x));
    return true;
}

private void retrieveMovies() {
    //TODO: I am unsure if I am handling correctly. When I favorite and unfavorite a movie, and then go back to the MainActivity, it is not displaying the correct item from the Spinner.
    //TODO: For example, favorites may be listed in the Spinner, however the screen may be displaying "TOP"
    //TODO: How could I tell if I am making unnecessary queries to Room? I know it is a project requirement, but I was not sure how to handle if I am making unnecessary calls
    //TODO: on screen rotation
    MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
    final LiveData> movies = viewModel.getMovies();
            movies.observe(this, new Observer>() {
        @Override
        public void onChanged(@Nullable final List movies) {
            for (Movie movie : movies) {
                String photoURL = "http://image.tmdb.org/t/p/w185" + movie.getPoster_path();
                Log.v("FAVORITE_URL", photoURL);
                mMovieURLS.add(photoURL);
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mMovieResultsList = movies;
                    mMovieResultsAdapter.notifyDataSetChanged();
                }
            });

        }
    });
}





@Override
protected void onResume() {
    super.onResume();
    ((GridLayoutManager) mMovieResults.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0);
}

private void calltoRetrofit(String mBaseURL) {
    mMovieURLS.clear();
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
    OkHttpClient client = new OkHttpClient
            .Builder()
            .addInterceptor(interceptor)
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(mBaseURL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    final ApiInterface apiInterface = retrofit.create(ApiInterface.class);

    Log.v("API", API_KEY);
    Call call = apiInterface.getImages(API_KEY);
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            Log.v("RESPONSE", response.body().toString());
            String totalPages = String.valueOf(response.body().getTotal_pages());
            Log.v("TOTAL", totalPages);
            mMovieResultsList = response.body().getResults();
            for (Movie movie : mMovieResultsList) {
                if (movie.getPoster_path() != null) {
                    String photoURL = "http://image.tmdb.org/t/p/w185" + movie.getPoster_path();
                    mMovieURLS.add(photoURL);
                }
                mMovieResultsAdapter.notifyDataSetChanged();
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            Log.v("FAILURE", t.toString());
        }
    });
}



@Override
public void onPointerCaptureChanged(boolean hasCapture) {

}

@Override
protected void onPause() {
    super.onPause();
    lastFirstVisiblePosition = ((GridLayoutManager)mMovieResults.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

}

public class MyAdapter extends RecyclerView.Adapter {


    public class ViewHolder extends RecyclerView.ViewHolder {

        protected ImageView mResultImage;

        public ViewHolder(View itemView) {
            super(itemView);
            mResultImage = itemView.findViewById(R.id.movie_poster_image);
        }
    }


    public MyAdapter(List mDataset) {
        mMovieResultsList = mDataset;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_poster_image, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        final String urlForPhoto = "http://image.tmdb.org/t/p/w185" + mMovieResultsList.get(position).getPoster_path();

        Picasso.get()
                .load(urlForPhoto)
                .into(holder.mResultImage);

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(getApplicationContext(), IndividualMovieActivity.class);
                i.putExtra("Movie", mMovieResultsList.get(position));
                startActivity(i);
            }
        });

    }

    @Override
    public int getItemCount() {
        return mMovieResultsList.size();
    }

}

public interface ApiInterface {
    @GET("?language=en-US")
    Call getImages(@Query("api_key") String api_key);
}

private boolean isOnline() {
    ConnectivityManager cm =
            (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

ianhanniball.. 5

RecyclerView仅保存其滚动位置,直到您调用为止setAdapter。在setAdapter没有数据的情况下通过调用,滚动位置将被丢弃(如果没有位置4,则无法滚动到位置4)。

您应该等待直到有数据可调用setAdapter



1> ianhanniball..:

RecyclerView仅保存其滚动位置,直到您调用为止setAdapter。在setAdapter没有数据的情况下通过调用,滚动位置将被丢弃(如果没有位置4,则无法滚动到位置4)。

您应该等待直到有数据可调用setAdapter


推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
author-avatar
你好2502898737
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有