ViewPager 在屏幕旋转后重新实例化无序的项目

2024-04-09

我正在使用一个ViewPager包含多个 ListView,其代码类似于答案中的代码无限ViewPager https://stackoverflow.com/questions/7440012/infinite-viewpager。这个想法是为谷歌日历应用程序提供类似日视图的东西(其来源似乎不可用;只有默认的日历应用程序是,但它使用ViewSwitcher) - 我想让用户看起来可以无限左右滑动,但实际上只有 3 个项目ViewPager,当用户点击页面 0 或 2 时,我们将 1 设置为当前页面并相应更新。

现在,这一切都有效了。然而,奇怪的是,当手机旋转并重建活动时(我避免使用configChanges目前),应用程序中的页面会再次实例化,但顺序不正确。顺序是 1->0->2,而不是 0->1->2,这会打乱应用程序中页面的顺序。

我的片段,在onActivityCreated():

mPagerAdapter = new ContinuousPagerAdapter(R.layout.my_listview, this);

// set the adapter
mViewPager = (ViewPager) getView().findViewById(R.id.agendaViewPager);
mViewPager.setOffscreenPageLimit(3);
mViewPager.setOnPageChangeListener(this);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setSaveEnabled(false);
// ...
mViewPager.setCurrentItem(1, false);
loadData();

寻呼机适配器:

import android.content.Context;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

public class ContinuousPagerAdapter extends PagerAdapter {

    OnPageInstantiatedListener pListener;
    ViewPager container;
    int childLayoutResId;

    @SuppressWarnings("unused")
    private ContinuousPagerAdapter() {
    }

    /**
     * @param childLayoutResId Layout resource ID of the children to be inflated
     */
    public ContinuousPagerAdapter(int childLayoutResId, OnPageInstantiatedListener pListener) {
        this.childLayoutResId = childLayoutResId;
        this.pListener = pListener;
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(View container, int position) {
        this.container = (ViewPager) container;

        // inflate a new child view
        LayoutInflater li = (LayoutInflater) container.getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        View childView = li.inflate(childLayoutResId, null, false);

        // add it to the view pager and return
        int count = this.container.getChildCount();
        int actualPos = count > position ? position : count;
        this.container.addView(childView, actualPos);
        pListener.onPageInstantiated(actualPos); // sometimes use 0 instead of actualPos, with different but still inconsistent results
        return childView;
    }

    @Override
    public void destroyItem(View container, int position, Object object) {
        ((ViewPager) container).removeViewAt(position);
    }

    public static interface OnPageInstantiatedListener {
        public void onPageInstantiated(int position);
    }

    /**
     * Needed to ensure all the items are instantiated
     */
    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
    }

    @Override
    public void finishUpdate(View container) {
    }
}

我不明白为什么页面在旋转后按 1->0->2 的顺序实例化。我也不保存状态。对此的任何见解都会有所帮助。


在仔细调试应用程序并查看之后ViewPager源码,我发现问题了。

应用程序第一次启动时mViewPager.setAdapter(mPagerAdapter)被调用后,页面会立即启动,应用程序将按其应有的方式工作。但是,当手机旋转时,调用setAdapter()推迟实例化页面,因为getWindowToken()由于窗口尚未准备好,因此返回 null。实例化被延迟,直到after onResume()在某个循环中被调用。

Calling setCurrentItem(1, false)使第一个页面成为主页面,因此它在其他页面之前被实例化,导致首先出现奇怪的 1->0->2 实例化。

解决方案? Use a Handler运行setCurrentItem()并在其他页面实例化后加载数据:

new Handler().post(new Runnable() {
    @Override
    public void run() {
        mViewPager.setCurrentItem(1, false);
        cleanupAndShowData();
    }
});

虽然我通常想避免使用Handlers,这似乎是迄今为止我找到的唯一选项,因为页面本身是在循环器中添加的。

EDIT: 即使上面也有一些问题。我最后打电话了mViewPager.setCurrentItem(1, false)仅在所有页面都已实例化之后(在onPageInstantiated()).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ViewPager 在屏幕旋转后重新实例化无序的项目 的相关文章

  • 如何让JComboBox中的内容居中显示?

    目前我有这个JComboBox 我怎样才能将其中的内容居中 String strs new String 15158133110 15158133124 15158133458 JComboBox com new JComboBox str
  • 使用ssl和socket的python客户端身份验证

    我有一个 python 服务器 需要客户端使用证书进行身份验证 我如何制作一个客户端脚本 使用客户端证书由 python 中的服务器使用 ssl 和套接字模块进行身份验证 有没有仅使用套接字和 ssl 而不扭曲的示例 from OpenSS
  • Android Jasper 报告

    Jasper Reporting 可以集成到 Android 应用程序中吗 我正在尝试从 jrxml 文件生成 PDF CSV 文本和 XLS 报告 但是 我没有看到 Android SDK 支持 net sf jasperreports
  • Bootstrap 3 / 显示模式不适用于 javascript 方式

    我用Modal http getbootstrap com javascript modalsBootstrap 3 0 的功能 我有这个代码 a href myNestedContent Open the modal containing
  • 在 VS2008 的 XAML 编辑器中禁用 Intellisense?

    有没有办法在 Visual Studio 2008 的 XAML 编辑器中禁用 Intellisense 打字时通常会消耗很大的性能 有时我会等待十秒或更长时间 直到列表自动弹出 似乎在 选项 gt 文本编辑器 gt XAML 中 Inte
  • 查询联系人 - 有时返回空游标

    我正在尝试查询联系人的显示名称 Override public void onActivityResult int requestCode int resultCode Intent data switch requestCode case
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即
  • 如何调试 Gulp 任务?

    如何调试我的中定义的 gulp 任务gulpfile js使用诸如 Google Chrome 调试器之类的调试器逐行单步执行任务的代码 对于 Node js 6 3 版本 您可以使用 inspect flag https nodejs o
  • 在 javascript 中使用 xPath 解析具有默认命名空间的 XML

    我需要创建一个 XML xPath 解析器 所有解析都必须在客户端进行 使用 JavaScript 我创建了一个 javascript 来执行此操作 在默认名称空间发挥作用之前 一切看起来都正常 我根本无法查询具有默认命名空间的 XML 我
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • ggplot2 的 fortify 函数出错

    我在 ggplot2 中使用 fortify 方法时收到此错误 Error in function classes fdef mtable unable to find an inherited method for function pr
  • 在门户中查看 Azure WebJob 计划?

    我创建了一个简单的 Azure WebJob 并通过 Visual Studio 集成制定了每天运行一次的计划 我已经部署了 WebJob 并看到它列在我在 Azure 上的应用程序中 schema http schemastore org
  • 嵌入式二进制资源 - 如何枚举嵌入的图像文件?

    我按照中的说明进行操作这本书 http www apress com book view 9781430225492 关于资源等的章节 我不太明白的是 如何替换它 images Add new BitmapImage new Uri Ima
  • 以 Rails 形式处理 MongoMapper EmbeddedDocument

    首先 我对一般编程和 Rails 都是新手 我选择 Rails 是因为它看起来是一种很容易上手的语言 对于我的项目 我将 MongoMapper 与 Rails 结合使用 我正在尝试以与文档相同的形式处理嵌入文档 我有以下模型 class
  • 在 for 循环比较中使用集合大小

    Java 中 Collections 的 size 方法是否有编译器优化 考虑以下代码 for int i 0 i
  • 小于或等于

    使用暂停命令我发现错误位于此代码的第一行 if choice 1 if energy gt m2enc set a enemhp enemhp m1hpd earmr pause set a energy energy m1enc set
  • CLion - 命令行程序参数

    当我分配给 运行 调试配置 程序参数 之类的 aaa bbb 然后打印它时 任何人都可以告诉我 JetBrains CLion 有什么问题吗 printf s n argv 1 我刚刚得到 aaa 而它必须是 aaa bbb 因为它们用双引
  • 从 npm 脚本运行时,eslint 不会报告任何错误

    我已经使用 npm init eslint config 安装了带有 typescript 的 eslint 然后将 lint 脚本添加到我的 package json 中 但是当我运行 npm script lint npm run li
  • 无法将 /root/.rnd 加载到 RNG 中

    我想使用 Windows Open SSL 生成服务器证书 当我运行此命令行时 出现此错误 我应该怎么办 Command openssl req new x509 days 3650 key ca key out ca crt Error
  • jQuery:动态添加 DOM 元素时尝试将函数挂钩到 onclick,但它立即执行该函数

    我正在使用 jQuery 动态 我的意思是在运行时 向页面的 DOM 添加一个 span 元素 create add task button document createElement span attr id activityNameH

随机推荐