首页 \ 问答 \ 何时PendingIntent被处置/删除?(When exactly does a PendingIntent get disposed/removed?)

何时PendingIntent被处置/删除?(When exactly does a PendingIntent get disposed/removed?)

我正在使用PendingIntent以及AlarmManagerBroadcastReceiver在用户指定的时间显示提醒。 我正在使用NotificationManager显示提醒。

在设置通知之前,我想要一个按钮来说“设置提醒”,并在设置通知后我希望按钮说“更改提醒” 。 一旦向用户显示通知,该按钮应再次说“设置提醒”

我正在使用相同的intent,context和相同的唯一id(myUniqueId)创建相同的PendingIntent ,以检查PendingIntent是否处于活动状态。

Intent intent = new Intent(context, ReminderReceiver.class);
boolean reminderActive = (PendingIntent.getBroadcast(context, myUniqueId, intent, PendingIntent.FLAG_NO_CREATE) != null);

现在这个工作,按钮文本正确显示。 但我发现,只要显示通知,除非我明确检索相同的PendingIntent并取消它,否则它不会被删除一段时间。 所以有一段时间,按钮仍然显示“Change Reminder”。

因此,假设除非我明确取消PendingIntent,它仍然存储在内存中的某个地方以进行垃圾收集,这是正确的吗?


I am using a PendingIntent along with AlarmManager and a BroadcastReceiver to show reminders at a user specified time. I am displaying the reminder using the NotificationManager.

Before a notification is set, I want a button to say "Set Reminder" and after the notification is set I want the button to say "Change Reminder". As soon as the notification is shown to the user, the button should again say "Set Reminder".

I am creating the same PendingIntent with the same intent, context and the same unique id (myUniqueId) to check whether the PendingIntent is active.

Intent intent = new Intent(context, ReminderReceiver.class);
boolean reminderActive = (PendingIntent.getBroadcast(context, myUniqueId, intent, PendingIntent.FLAG_NO_CREATE) != null);

Now this works and the button text is displayed properly. But I figured out that as soon as the notification is shown, unless I explicitly retrieves the same PendingIntent and cancels it, it's NOT removed for a while. So for sometime, the button still says "Change Reminder".

So is it correct to assume that unless I explicitly cancels the PendingIntent it's still stored somewhere in the memory to be garbage collected?


原文:https://stackoverflow.com/questions/12883821
更新时间:2024-03-24 18:03

最满意答案

根据文档 ,在API级别17中添加的View.generateViewId()将生成适合在setId(int)使用的值。 此值不会与构建时在aid为R.id生成的ID值冲突。

我尝试使用View.generateViewId()来了解它的行为方式。 以下是我的发现。

  • 生成的ID将从1开始,每次调用时都会递增(1,2,3 ......)
  • generateViewId() 将保留返回的最后一个ID ,并将在整个应用程序生命周期中从那里继续。 例如,如果设备旋转前的最后一个ID为4,则旋转后的下一个ID将为5。

重要的是要注意,例如,如果您在应用程序的onCreate()方法中通过每次调用generateViewId()在运行时设置视图,则在设备旋转后,默认情况下再次调用onCreate()并且您的视图将会获得与轮换前不同的ID

Android具有自动恢复视图状态的功能 - 例如,您输入EditText视图的文本,检查CheckBox的状态 - 在设备轮换后,但它仅在视图具有持久ID时才有效 。 因此,在上面的示例中,此状态恢复将不起作用 - 您的EditText视图将丢失输入,您必须键入您需要再次键入的内容 - 因为视图每次生成时都会收到不同的ID。 要解决此问题,您需要通过活动生命周期维护ID。

我发现Android为数十亿的XML中定义的对象分配ID。 这是从我的应用程序中获取的具有几个预定义ID的真实ID:2131427423。因此,在不调用generateViewId()情况下自行判断使用低ID 似乎是非常安全的。 在我的简单应用程序中,我通过分配从1开始的ID,增加1来模仿它,并且它起作用。 这是一个从我的应用程序中提取的示例:

public class MainActivity extends AppCompatActivity {
    // since our lastAllocatedViewId will reset on device rotation
    // regenerated views will receive the same ID
    private int lastAllocatedViewId = 0;

    private ArrayList<QuizQuestions> quizQuestions;

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

        // read quizQuestions from xml at runtime;
        quizQuestions = parseQuizQuestionsXml();

        // we will dynamically add quiz question views to this view
        // depending on how many quizQuestions are in the XML config
        LinearLayout container = (LinearLayout) findViewById(R.id.quiz_questions_container);

        // generate a view for each quiz question
        for (int i = 0; i < quizQuestions.size(); i++) {
            LinearLayout quizQuestionView = (LinearLayout) inflater.inflate(R.layout.quiz_question_template, parent, false);

            quizQuestionView.setId(lastAllocatedViewId++);

            (...) // do some work on our newly generated view

            // then add it to the quiz questions container
            container.addView(quizQuestionView);
        }
    }
}

According to the documentation, View.generateViewId() added in API level 17 will generate a value suitable for use in setId(int). This value will not collide with ID values generated at build time by aapt for R.id.

I experimented with View.generateViewId() to find out how it behaves. Here are my findings.

  • Generated ID will begin from 1 and will be incremented by each time it is called (1, 2 , 3...)
  • generateViewId() will maintain the last ID returned and will continue from there throughout app life cycle. For example if last ID before device rotation was 4, next ID after rotation will 5.

It is important to note that, for instance, if you are setting up views at runtime in your app's onCreate() method by calling generateViewId() every time, after your device rotates, by default onCreate() is called again and your views will receive a different ID than before rotation.

Android has a feature to automatically restore your views state – for instance, text you enter into an EditText view, checked state of a CheckBox – after device rotation, but it only works if the views' have persistent IDs. So in the above example, this state restoration will not work – your EditText view will lose input and you have to type whatever you need to type in again – as views will receive a different ID every time they are generated. To work around this problem, you need to maintain IDs through activity life cycle.

I found out that Android assigns IDs for objects defined in XML in the magnitude of billions. This is a real life ID taken from my app having only a few predefined IDs: 2131427423. So it seems to be pretty safe to use low IDs on your own discretion without ever calling generateViewId(). In my simple app I mimicked it by assigning IDs beginning from 1, increasing by one, and it worked. Here is an example, extracted from my app:

public class MainActivity extends AppCompatActivity {
    // since our lastAllocatedViewId will reset on device rotation
    // regenerated views will receive the same ID
    private int lastAllocatedViewId = 0;

    private ArrayList<QuizQuestions> quizQuestions;

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

        // read quizQuestions from xml at runtime;
        quizQuestions = parseQuizQuestionsXml();

        // we will dynamically add quiz question views to this view
        // depending on how many quizQuestions are in the XML config
        LinearLayout container = (LinearLayout) findViewById(R.id.quiz_questions_container);

        // generate a view for each quiz question
        for (int i = 0; i < quizQuestions.size(); i++) {
            LinearLayout quizQuestionView = (LinearLayout) inflater.inflate(R.layout.quiz_question_template, parent, false);

            quizQuestionView.setId(lastAllocatedViewId++);

            (...) // do some work on our newly generated view

            // then add it to the quiz questions container
            container.addView(quizQuestionView);
        }
    }
}

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。