Activity 恢复时的 Android 内部类 TextView 参考

2024-04-13

我有一个扩展 CountDownTimer 的内部类。基本上它是一个简单的倒计时器,用于更新活动中的 TextView 并在计时器完成时播放声音。内部类的代码是:

public class SetTimer extends CountDownTimer
{

    public SetTimer(long millisInFuture, long countDownInterval)
        {
            super(millisInFuture, countDownInterval);
        }

    @Override
    public void onFinish()
        {
            timeLeft.setText("0");
            Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            Ringtone r=RingtoneManager.getRingtone(getApplicationContext(), notification);
            r.play();

        }

    @Override
    public void onTick(long millisUntilFinished)
        {
            String t;
            t=String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished), TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished)
                    -TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)));
            timeLeft.setText(t);
        }

}

创建并引用 TextView 的代码是:

TextView timeLeft;

并在 onCreate 方法中:

timeLeft=(TextView) findViewById(R.id.txtTimeLeft);

在我旋转显示器之前,这一切正常。此时计时器仍在运行,并在最后播放声音,但它不会更新 TextView。 TextView 在类的顶部声明,并在活动的 onCreate 方法中引用。如果我重新启动计时器,它就会起作用。我使用 Log.d 检查 onTick 方法是否仍然被调用,确实如此。我的猜测是对 TextView 的引用已更改,但我不知道如何将其设置回计时器。我尝试在 onTick 方法中声明一个 TextView 并更新它,然后它会获取对 TextView 当前实例的引用,但这也不起作用。唯一需要注意的是,SetTimer 对象是在用户单击按钮时创建的。该代码是:

timer=new SetTimer(interval, 100);

timer.start();

关于如何让 SetTimer 在屏幕旋转后不断更新 TextView 有什么想法吗?


Update我完全重写了答案,因为我乍一看并没有注意到你的代码中有什么可怕的事情。

您可能会泄漏资源,而您的应用程序不会崩溃这一事实 - 可能只是时间问题。首先,你的内心SetTimer类隐式持有对Activity(我猜,你在 Activity 中声明了这个类,不是吗?)。这会阻止你Activity免于被垃圾收集,我猜,这就是为什么在将值设置为 a 时不会收到异常的原因TextView那是“看不见的”。

所以你应该将你的类声明为私有静态类, 静态类(内部类),或者公开课(在它自己的文件中)。这样,您将不会保留对 Activity 的隐式引用,并且在其被销毁时也不会导致内存泄漏。

但现在您将无法访问textview直接,因为它是您的成员Activity班级。我们这样解决吧:

  1. 在SetTimer内部声明一个接口:

    interface OnTickUpdateListener{
        public void onTickUpdate(String text);
    }
    
  2. 在 SetTimer 中声明此类接口的实例并修改构造函数:

    public class SetTimer extends ... {//this class IS IN IT's OWN FILE!!!!
        private OnTickUpdateListener listener;
    
        public void registerListener(OnTickUpdateListener listener){
            this.listener = listener;
        }
        public void unregisterListener(){
             this.listener = null;
        }
    ...
    }
    
  3. 让我们在计时器计时时触发监听器:

    @Override
    public void onTick(long millisec){
        if(listener != null){
            String t;
            t = String.valueOf(millisec);//or whatever
            listener.onTickUpdate(t);
        }
    }
    
  4. 现在,让您的 Activity 实现您的界面:

    public class MyActivity extends Activity implements SetTimer.OnTickUpdateListener{
        @Override
        public void onTickUpdate(String text){
            textView.setText(text);
    }
    

现在到更困难的部分。当 Activity 被销毁时,我们需要保存一个 SetTimer 实例。将 SetTimer 放入对用户不可见的保留 Fragment 中将是一个很好的技巧,这将像“不朽容器”一样工作:)

  1. 创建一个Fragment类:

    public class MyFragment extends Fragment{
    
        public static final String TAG = MyFragment.class.getSimpleName();
        private SetTimer timer;
        private static final int interval = 10;
        private MyActivity myActivity;
    
    
        @Override
        public void onAttach(Activity activity){
            super.onAttach(activity);
            this.myActivity = (MyActivity) activity;
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setRetainInstanceState(true);
            timer = new SetTimer(interval, 10);
            timer.start();
        }
    
        @Override
        public void onActivityCreated(Bundle state){
            super.onActivityCreated(state);
            timer.registerListener(myActivity);//activity should receive ticks
        }
    
        @Override
        public void onDetach(){
            super.onDetach();
            timer.unregisterListener();//ensure we do not post a result to non-existing  Activity
        }
    }
    
  2. 最后,将您的 MyFragment 添加到onCreate我的活动方法:

    public class MyActivity extends Activity implements SetTimer.OnTickUpdateListener{
        private MyFragment fragment;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            FragmentManager fm = getFragmentManager();
            fragment = (MyFragment) fm.findFragmentByTag(MyFragment.TAG);
            if(fragment == null){
                fragment = new MyFragment();
                fm.beginTransaction().add(R.id.container, fragment, MyFragment.TAG).commit();
    
            }
        }
    

这样,我们在 Activity 重新创建时恢复现有片段,并且 MyFragment 将新的 MyActivity 注册为侦听器,它将接收更新更新。

PS:这是我从头开始写的,没有测试它,所以如果您遇到任何错误 - 请发布它们,以便我们解决。

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

Activity 恢复时的 Android 内部类 TextView 参考 的相关文章

  • 查看寻呼机 - 使用静态变量以编程方式滑动到下一页

    我想在我的 ViewPager 中以编程方式制作幻灯片 我的问题是 滑动事件是由放置在 ViewPager 保存的片段内部的按钮调用的 我知道代码 viewpager setCurrentItem int index 现在我的想法是使 Vi
  • Kapt 未在即时应用程序功能模块中生成类

    我在我的 Android 应用程序中使用 dagger2 即使没有错误 它也不会生成匕首组件类 我已经在设置中启用了注释处理器并重新启动了我的 android studio 但这对我来说不起作用 我也读过这个帖子Dagger2 不生成 Da
  • 处理 Android 锁屏上的音量变化?

    我想做的是 能够在 android 4 4 上的锁屏上捕获音量增大 减小按钮操作 Google Cast 设计清单 https developers google com cast docs design checklist sender
  • 使用 GoogleServices 插件时忽略 Gradle ArchivesBaseName

    我经常使用 archivesbasename 来重命名我的输出 apk 但自从使用 google services 插件后 它就被忽略了 我能做些什么来让它再次工作吗 下面附上了我完整的 build gradle 感谢您的指点 apply
  • Android自定义控件命名空间问题

    我一直在为 Android 开发自定义控件 尽管我尝试按照建议进行操作here https stackoverflow com questions 4495511 how to pass custom component parameter
  • 如何从一个活动中完成一系列开放的子活动?

    我正在尝试为我的应用程序制作一个退出按钮 无论如何 我能够跟踪我的应用程序中的所有活动实例 然后完成它们 但在某些情况下 仍有一些活动仍然存在 不知道怎么办 有没有什么方法可以杀死android中的特定应用程序 或者我可以通过任何其他方式退
  • 导航组件参数默认值

    在导航组件中 将参数从第一个片段发送到第二个片段时 默认值不会从导航图中获取哪个集合 这是我的代码 导航图 xml
  • 有没有办法将搜索栏添加到我的实际首选项屏幕?

    我一直看到有关添加您自己的搜索栏首选项的教程 但它不在我实际的 prefs xml 中 有什么方法可以在我的主偏好设置屏幕中添加一个 或者我必须将其分开 Google 似乎有 2 个滑块首选项 搜索栏首选项 https github com
  • 毕加索磁盘缓存

    我正在使用 Picasso 从 URL 加载图像 Picasso with getApplicationContext load product getImageUrl into imageView 据我所知 每次都会访问该网址 而不是缓存
  • Android 中的 java.util.Observable 是线程安全的吗?

    Android 中的 java util Observable 是线程安全的吗 这文档 http developer android com reference java util Observable html说只有deleteObser
  • ListView:防止视图回收

    我有一个使用回收视图的 ListView 我试图阻止视图被回收 所以我使用 setHasTransientState android support v4 view ViewCompatJB setHasTransientState Vie
  • Android 8.1 中 Activity 自行旋转并恢复正常

    我的应用程序在所有 Android 版本上运行良好 但我注意到在 Android 8 1 0 Oreo 中 当我将屏幕从纵向活动转到横向活动时 以及当我按后退按钮时 它会显示异常行为 屏幕自动从横向旋转并恢复正常 看起来 Activity
  • 需要在 Android 中伪造正在扫描的 NFC 标签

    好的 我有一个应用程序 此应用程序仅在扫描 NFC 标签 任何标签 时才会完成任务 唯一的问题是 我没有任何 nfc 标签 无论如何 我正试图消除对卡的需要 所以我需要的是一种 伪造 使其看起来 就像已扫描 nfc 标签的方法 我可以编写应
  • Android httpclient文件上传数据损坏和超时问题

    我在 Android 中上传图像时遇到问题 我正在使用 apache httpmime 4 1 lib 代码是这样的 MultipartEntity reqEntity new MultipartEntity HttpMultipartMo
  • Android Drawable 绘图性能?

    在我看来 我有一个简单的 ARGB 可绘制对象 大约需要 2 毫秒才能绘制 但我可以在 0 5 毫秒内绘制与位图相同的文件 只是一些快速代码 我真的不能认为它是一个选项 优化可绘制对象的绘制速度的最佳方法是什么 这取决于可绘制的数量以及每个
  • 使用后退按钮启动 Activity

    我正在 Android 中开发一个应用程序 我正在寻找解决方案 有一个活动 例如 A1 通过单击按钮 用户可以转到另一个活动 例如 A2 现在 一旦用户完成 A2 活动 他就会单击后退按钮 返回到上一个活动 A1 这是众所周知的事实 A1此
  • 从Android客户端登录appengine

    我正在尝试登录应用程序引擎并访问应用程序引擎中的用户服务API 基本上我希望能够看到谁登录了我的 servlet 我正在使用从 android 获取 authtoken 然后从应用程序引擎获取 ASID 或 SACID cookie 的身份
  • Android复杂布局线性和相对

    I have to implement a layout like shown in the diagram and I do not know the best combination to achieve the required de
  • 从 sqlite 和 mysql 加载数据微调器

    我试试这个tutorial http nielpoenya blogspot com 2012 08 tutorial android spinner dari database html加载Spinner from sqlite and
  • Android Espresso - 如果未选中,请单击复选框

    I have onView withId R id check box perform click 但我只想在尚未选中该复选框时执行此操作 我怎样才能在浓缩咖啡中做到这一点 我还想根据其之前的状态来切换复选框 开关 起初 我尝试用此方法打开

随机推荐

  • Scala 编译器有哪些特殊类型?

    Scala 非常重视如何将看似语言的功能实现为库功能 是否有该语言特别处理的类型列表 是在规范中还是作为实现细节 例如 这包括优化元组的客场匹配 与模式匹配 推导式 try catch 块和其他语言结构相关的特殊约定又如何呢 String
  • CodeBuild 不报告失败的测试

    我正在使用 CodeBuild 构建我的 NPM 项目 我的构建规范中有一个特定的报告组 并且我正在使用 Jest 和npm test命令 当所有测试通过后 将成功报告给 CodeBuild 报告组 但是 如果其中一项测试失败 我会收到错误
  • 为什么 Google Analytics 不跟踪任何事件?

    我已经实现了几乎标准的示例
  • Azure DevOps - 自定义任务 - 具有 Azure 身份验证的 PowerShell

    到目前为止 我使用 Azure PowerShell 任务在 Azure 上下文中执行 PowerShell 脚本 https learn microsoft com en us azure devops pipelines tasks d
  • 大浮点和的精度

    我正在尝试对正递减浮点数的排序数组求和 我发现对它们求和的最佳方法是开始从最低到最高将数字相加 我编写此代码是为了提供一个示例 但是 从最高数字开始的总和更精确 为什么 当然 1 k 2之和应该是f 1 644934066848226 in
  • 在 Java 循环中重新声明变量

    在Java中 我们不能将一个变量与另一个同名变量声明在同一作用域中 int someInteger 3 int someInteger 13 语法错误 无法编译 但是 如果我们将其放入循环中 for int i 0 i lt 10 i in
  • Google 云端硬盘哑剧类型列表? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 As per https developers google com drive manage uplo
  • 如何避免右侧滚动条与顶部导航栏(引导程序)重叠?

    我有一个网站 导航栏固定在顶部 导航栏位于左侧 当网站需要滚动时 右侧的滚动条与顶部导航栏重叠 我希望导航栏从顶部导航栏下方开始 我摆弄了一个问题的例子 https jsfiddle net jsmnsLm7 https jsfiddle
  • 不受信任的 URL 字符串的安全 Process.Start 实现

    我的目标是在用户默认浏览器中安全地打开网页 该网页的 URL 被视为 不受信任 将其视为使用该软件打开的文档中的链接 但该文档可能来自任何地方 并且其中的链接可能是恶意的 我想避免有人将 C Windows malicious code e
  • 来自连接表的 SQL 计数

    我有一个表 lijsten 一个表 werknemerlijsten 和一个表 categorieen 现在我正在使用查询来获取计数 SELECT id naam beschrijving count wl werknemer id as
  • 复杂的查询应该写在Repository层还是Service层?

    我计划将我们的数据访问层迁移到使用存储库模式和工作单元 我确实知道存储库将帮助我轻松地将持久性存储 数据库 集合等 和技术 例如 EF 更改为 MongoDB 所以我注意到存储库实现的一些关键点 例如 Return IEnumerable代
  • 从数组 THREE.js 创建纹理

    我正在研究地形生成器 但我不知道如何处理颜色 我希望能够生成一张占据整个 PlaneGeometry 的图像 我的问题是如何根据我的高度图创建一个覆盖整个 PlaneGeometry 没有环绕 的单个图像 我可以想到一种方法 但我不确定它是
  • 更改 TabBarItem 的 ViewController

    是否可以更改 替换 UITabBarController 中选项卡之一的 ViewController 和 View 我想从特定选项卡以任意顺序在 3 个不同的视图控制器之间切换 这就是导航控制器不可能的原因 它们是使用 setViewCo
  • 为什么 TBitBtn 中包含的字形如此丑陋且过时? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Jetty 通过 Maven 正确运行,但作为 jar 运行不正确

    如果我的标题具有误导性 不正确 请提出更具描述性的内容 这是我能想到的最好的内容 我已经使用 spring roo 创建了自己的网络应用程序 但尚未编辑任何代码 我正在使用 Maven 和 jetty 构建并运行 Web 应用程序 当我执行
  • 使用 javascript 自动增加 firebase 中的值

    你好 我正在开发一些 firebase 项目 我可以通过 javascript 将我的数据保存到 firebase 数据库中 但我无法弄清楚如何自动增加数据库的子值 我的子值是 duyuru 您可以在下面看到详细信息 我在下面分享我的代码
  • 如何使用 Groovy 修剪列表中的所有元素?

    我需要在 groovy 或 grails 中修剪列表中的所有元素 最好的解决方案是什么 假设它是一个字符串列表 并且您想要修剪每个字符串 您可以使用扩展运算符 http groovy codehaus org Operators Opera
  • 从数组随机 URL 重定向

    政治动物 contentscript js 加载到清单 json 中列出的每个页面上 该插件将新闻网站网站上的所有图像替换为以下图片 穿西装的动物 作为对新闻的评论 专为 Web 2 打造 2013 年 11 月 20 日 随机图像数组 v
  • 以编程方式将 TabLayout 中的选项卡文本颜色更改为不同颜色

    我的屏幕上有 7 个日期选项卡 选择选项卡时 文本为黑色 而其他可选选项卡的颜色为白色 如果日期是另一个月 我希望文本颜色为灰色 我假设第一个选项卡是 0 第二个选项卡是 1 一直持续到 6 如图所示 我想更改选项卡 3 选项卡 4 选项卡
  • Activity 恢复时的 Android 内部类 TextView 参考

    我有一个扩展 CountDownTimer 的内部类 基本上它是一个简单的倒计时器 用于更新活动中的 TextView 并在计时器完成时播放声音 内部类的代码是 public class SetTimer extends CountDown