- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个扩展 CountDownTimer 的内部类。基本上它是一个简单的倒数计时器,它更新 Activity 中的 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 在类的顶部声明,并在 Activity 的 onCreate 方法中引用。如果我重新启动计时器,它就会工作。我使用 Log.d 来检查 onTick 方法是否仍在被调用,它确实被调用了。我的猜测是对 TextView 的引用已更改,但我不知道如何将其设置回计时器。我尝试在 onTick 方法中声明一个 TextView 并更新它,然后计算它会获取对 TextView 的当前实例的引用,但这也没有用。唯一需要注意的是,当用户单击按钮时,将创建 SetTimer 对象。该代码是:
timer=new SetTimer(interval, 100);
timer.start();
关于如何让 SetTimer 在屏幕旋转后继续更新 TextView 有什么想法吗?
最佳答案
更新 我完全重写了答案,因为乍一看我没有注意到您的代码中有什么可怕的地方。
您可能正在泄漏资源,而您的应用不会崩溃这一事实 - 可能只是时间问题。首先,您的内部 SetTimer 类隐含地持有对 Activity 的引用(我猜,您在 Activity 中声明了这个类,不是吗?)。这可以防止您的 Activity 被垃圾收集,我想,这就是为什么在将值设置为“看不见”的 TextView 时您不会收到异常的原因".
因此您应该将您的类声明为私有(private)静态类、静态类(内部类)或公共(public)类(在它自己的文件)。这样,您就不会持有对 Activity 的隐式引用,也不会在它被销毁时导致内存泄漏。
但现在您将无法直接访问 textview,因为它是您的 Activity 类的成员。让我们这样解决:
在 SetTimer 中声明一个接口(interface):
interface OnTickUpdateListener{
public void onTickUpdate(String text);
}
在您的 SetTimer 中声明此类接口(interface)的实例并修改构造函数:
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;
}
...
}
让我们在计时器计时时触发监听器:
@Override
public void onTick(long millisec){
if(listener != null){
String t;
t = String.valueOf(millisec);//or whatever
listener.onTickUpdate(t);
}
}
现在,让您的 Activity 实现您的界面:
public class MyActivity extends Activity implements SetTimer.OnTickUpdateListener{
@Override
public void onTickUpdate(String text){
textView.setText(text);
}
现在是更难的部分。我们需要在 Activity 被销毁时保存一个 SetTimer 实例。将 SetTimer 放入用户不可见的保留 Fragment 中将是一个很好的技巧,它的工作方式很像“不朽容器”:)
创建 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
}
}
最后,在 MyActivity 的 onCreate
方法中添加您的 MyFragment:
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 时恢复现有 fragment ,MyFragment 将新的 MyActivity 注册为监听器,它将接收滴答更新。
PS:我是从头开始写的,没有测试它,所以如果您遇到任何错误 - 请发布错误,以便我们解决问题。
关于 Activity 恢复时的 Android 内部类 TextView 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22511248/
有什么方法可以恢复删除的元素吗? 这是我删除元素的代码 myFunction() { var width = window.innerWidth; var February = doc
我有一个 TokuDB 表,由于某种原因缺少 ***_status.tokudb 文件。 我还不确定文件是否由于 TokuDB 崩溃而丢失。 问题是: 有没有办法从主要文件和关键文件(我可以从 tok
我正在 Windows 7 (x86) 上运行带有 Workbench 6.3.8 的 32 位 MySQL Server 5.7.22 本地实例(必须选择 32 位版本 - 所以,较旧的版本)。 我
1、备份 <% SQL="backup database 数据库名 to disk='"&Serve
1、ASP中怎么实现SQL数据库备份、恢复! 答:asp在线备份sql server数据库: 1、备份 <% SQL="ba
我在 R 中使用 stats::filter 函数来理解 R 中的 ARIMA 模拟(如在函数 stats::arima.sim 中)和估计。我知道 stats::filter 将线性过滤器应用于向量
我已经浏览了示例应用程序的文档和代码,并发现 files/objectbox/objectbox/data.mdb 是存储所有数据的默认文件。 假设我的理解是正确的,我有几个问题找不到文档: 我想在我
为了恢复非续订订阅类型的 InAppPurchase,我已经实现了服务器来处理此问题。 但在购买过程中,iTunes 有时不会要求用户验证他们的卡详细信息, 在这种情况下,它会在后台发送应用程序并显示
我的问题是寻找cocos2d游戏期间暂停/恢复状态(包括所有需要保存的数据信息)的设计解决方案。 包括但不限于以下情况: 1).用户选择退出,然后弹出一个对话框供用户选择“直接退出”、“暂停”; 2)
在 Mercurial 中,我有一个旧的变更集,除了对单个文件的更改外,它都很好。我将如何恢复对该单个文件的更改? 即使只是能够在上一个变更集中查看文件的状态也会很好,然后我可以剪切和粘贴。 我的 M
我的一项职能遇到了困难。我想做的是计时器在页面加载后立即启动,并且只有一个带有启动/恢复的按钮。我无法在代码中找出需要更改功能的位置。有人可以帮助我吗?谢谢! HTML: , Javascr
我正在阅读Scrap your type classes 。这为类型类提供了替代方案。然而,我被Paul Chiusano的评论所困扰。其中讨论了恢复 do 表示法 语法。 坦白说,我无法理解 ret
当 OrientDB 因某人重新启动机器而非正常关闭时,OrientDB 最终会处于数据恢复失败的状态。对于如何从这种不正常的关闭中正常恢复有什么建议吗?我们正在寻找系统在断电期间能够自行恢复的方法。
我正在构建一个 Electron 应用程序,如果发生崩溃,它必须重新加载渲染进程窗口。 目前我可以从主进程重新启动应用程序 app.relaunch(); app.quit(); 但我无法检测到窗口崩
我有 3 个 Activity ,比如说 MainActivity、 Activity 2 和 Activity 3。 在 MainActivity 中,我有一个按钮(开始/停止),当我单击此按钮时,
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
Twilio 是否支持暂停和恢复内容播放。换句话说,我有相当长的文件将播放给调用者,并且我正在尝试找到一种方法来实现暂停和恢复功能。在播放某些内容的过程中,我希望用户能够按数字暂停,然后再次按数字从音
我已经提交了 A、B、C、D 和 E。我意识到在提交 B 中发生了一些非常糟糕的事情,所以我想回到 A,这次正确地进行之前搞砸了 B 的更改,然后重新应用 C 、 D 和 E 自动。 您可能想知道为什
我的一个文件被“标记为文本”,图标也发生了变化。实际上这是一个 PHP 文件。我尝试过使用 Help -> Find Action -> Mark As 尝试将其恢复为 PHP 突出显示,但它不起作用
我有一些 SSE 程序,可以将循环中的内存归零,当指针未对齐时,它会引发 SIGSEGV进入我的处理程序。我可以在此类处理程序中获取更多信息吗例行公事,现在我不知道它是在哪里完成的,我也可以吗以某种可
我是一名优秀的程序员,十分优秀!