【问题标题】:Reset Value of an Integer at A Specific Time of Day在一天中的特定时间重置整数的值
【发布时间】:2015-03-08 11:08:13
【问题描述】:

我目前有一个片段,它有几个按钮并包含一个 onClickListener。每次单击其中一个按钮时,计数器变量都会增加 1,并使用 SharedPreferences 将其设置为另一个 Fragment 中的 TextView 的文本。

即使在应用完全关闭后,计数器也会保持不变,并会在应用的后续运行中出现。

我的新目标是在每天结束时将计数器重置为 0(确切地说是 23:59:00)。

我决定避免使用 Google 搜索来解决这个问题,并在 Android 开发者文档中找到了 TimerTask、Calendar、Timer 和 Date API;我试图让它与这些 API 一起工作。不幸的是,它没有按照我的计划进行。变量 设置回 0,但它们保持为零,并且只会递增到 1,并且每次我退出应用程序时都会回到 0。

有没有更好的方法来解决这个问题?还是我的方法够用,只需要调整/更改一些代码?

其中一个问题可能是我在哪里更改了计数器变量引用(如果是,我应该在哪里更改它)?

这是我的尝试:

第一个片段

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflating the layout
        View v = inflater.inflate(R.layout.starting_fragment, container, false);

        //Instantiate new Timer
        Timer timer = new Timer();
        // Creates a Calendar object that specifies a specific time of day
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.set(Calendar.HOUR_OF_DAY, 20);
        cal.set(Calendar.MINUTE, 57);
        cal.set(Calendar.SECOND, 00);
        cal.set(Calendar.MILLISECOND, 00);

        // Instantiate a day object and use the time of day from cal object as its data
        Date date = cal.getTime();

        TimerTask tt = new TimerTask() {
            // Sets the counter variables back to 0
            @Override
            public void run() {
                COUNT_OOL = 0;
                COUNT_WTE = 0;
                COUNT_BLO = 0;
                COUNT_BLK = 0;
                COUNT_HBL = 0;
                COUNT_GRN = 0;
                COUNT_MTE = 0;

            }
        };
        // Resets the counter variables (to 0) at the time specified by the date object
        timer.schedule(tt, date);

        // Stores count for each button back into their respective count variable
        // Initializes the value from previous runs of app to subsequent runs of app
        // This way, count variables will never get set back to 0 after onDestroy()
        COUNT_OOL = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("oolongCount", 0);
        COUNT_WTE = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("whiteCount", 0);
        COUNT_BLO = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("bloomingCount", 0);
        COUNT_BLK = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("blackCount", 0);
        COUNT_HBL = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("herbalCount", 0);
        COUNT_GRN = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("greenCount", 0);
        COUNT_MTE = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("mateCount", 0);

递增计数器变量的 onClick 方法:

 @Override
    public void onClick(View view) {
        int id = view.getId();
        /*
         * Use the View interface with OnClickListener to get the Button ID's
         * Then you can run a switch on the Buttons (because normally switches
         * cannot be run on buttons
         */

        if (id == R.id.tea_type1) {
            Builder oolongBuilder = new AlertDialog.Builder(StartingFragment.this.getActivity(),
                    AlertDialog.THEME_HOLO_LIGHT);

            oolongBuilder.setPositiveButton("Hot",
                    //Starts OolongTeaActivity for hot tea when clicked
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface arg0, int arg1) {
                            Intent i = new Intent(StartingFragment.this.getActivity(),
                                    OolongTeaActivity.class);
                            StartingFragment.this.getActivity().startActivity(i);
                        }
                    });

            oolongBuilder.setNeutralButton("Iced",

                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent i = new Intent(StartingFragment.this.getActivity(),
                                    ColdOolongTeaActivity.class);
                            StartingFragment.this.getActivity().startActivity(i);

                        }
                    });

            oolongBuilder.setTitle("Oolong Tea");
            oolongBuilder.setMessage("How Do You Like Your Tea?");

            AlertDialog oolongDialog = oolongBuilder.create();
            oolongDialog.show();

            COUNT_OOL++;
            SharedPreferences pref1 = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor1 = pref1.edit();
            editor1.putInt("oolongCount", COUNT_OOL);
            editor1.commit();

        }

SecondFragment(将计数器设置为 TextViews 的文本)

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_tea_counter, container, false);

        oolongCounterText = (TextView) rootView.findViewById(R.id.oolong_counter_tv);

        SharedPreferences pref1 = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE);
        Integer counter1 = pref1.getInt("oolongCount", 0);
        String s1 = String.valueOf(counter1);
        oolongCounterText.setText(s1);

【问题讨论】:

  • 您想使用AlarmManager 安排您的夜间计数器重置。
  • @MikeM。我该怎么做?我现在正在查看文档,所以看来我必须从 AlarmManager am = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); am.setExact(AlarmManager.RTC, System.currentTimeMillis(), pendingintent); 之类的东西开始
  • @MikeM。我查看了文档,但我不明白的是 PendingIntent。我没有尝试使用意图,因为我没有使用任何活动。这种变量的更新仅在两个片段之间进行。你能帮我解释一下吗?
  • 最简单的做法可能是实现一个BroadcastReceiver,它更新onReceive()中的SharedPreferences设置,在manifest中注册它,并通过getBroadcast()获取PendingIntent。
  • @MikeM。我创建了一个 BroadCastReceiver 类并在我的第一个 Fragment 中设置了 AlarmManager。我想我快到了,但我不确定如何处理我的 Broadcast 类中的 SharedPreferences,因为它与 Fragment 中的计数器有关。所以我想要更多的帮助...FirstFragment with Alarmanager && Broadcast Activity

标签: android android-fragments reset


【解决方案1】:

我个人会考虑使用AlarmManagerCalendar 来设置时间。然后,您将触发 Service 来完成您需要做的所有事情。

Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 0);
PendingIntent pi = PendingIntent.getService(context, 0,
            new Intent(context, MyService.class),PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                                AlarmManager.INTERVAL_DAY, pi);

将 MyService 替换为实际的Service,当服务启动时,它可以: 1)将数字重置为0 2)检查应用程序是否正在运行,看看您是否需要立即更新文本框,或者是否可以等待用户启动应用程序 3) 停止服务

在遵循此代码之前需要调查的事项:

确保AlarmManager 适合您,重启后不会出现重复警报(感谢Jawnnypoo 澄清这一点)请参阅下面的评论,其中他链接到BroadcastReceiver,以便AlarmManager 将在重启后运行。

【讨论】:

  • 这是解决此问题的好方法,我可以 100% 肯定地告诉您,在重新启动后不会出现重复警报。您需要通过设置广播接收器并在清单中设置权限来在重新启动时重新注册重复警报。在此处查看更多示例:stackoverflow.com/questions/26138587/…
  • 感谢您的纠正,我已根据您的建议编辑了我的回复(我在答案中链接了您)
  • 我认为在启动时使用BroadcasterReceiver 来注册警报有点过头了。也许该应用程序甚至几天都不会使用。
【解决方案2】:

也许只存储一年中的某一天并与一年中的当前日期进行比较。

dayOfYear = DateFormat.format("D", new Date())

if (dayOfYear != lastResetDay) {
    resetCounters();
}

【讨论】:

  • 如果应用程序在使用一年后打开,则会出现错误。
  • 没有回答主要问题:您是什么时候执行此检查的?
  • dayOfYear = DateFormat.format("YD", new Date()) 这将解决使用后一年的问题。这个检查可以随时运行,虽然我不熟悉 Android 不知道什么是理想的。
  • dayOfYear 是什么类型的对象?我将如何存储 lastResetDay?
  • dayOfYear 应该是一个 INT。不熟悉 Android 将其存储在哪里,但通常将设置存储在哪里
【解决方案3】:
  • 只需保存上次在首选项中重置计数器的时间。
  • 片段第一次启动时:
    • 它会检查计数器上次重置的时间并可能会重置它们
    • 它通过AlarmManager 为下一个午夜注册一个警报,引发广播意图
    • 它注册一个广播接收器。
  • 当广播接收器收到意图时,它会重置计数器、通知片段并为下一个午夜注册警报。
  • 如果活动停止,请移除您的广播接收器并取消您的闹钟,这样应用程序就不会执行任何不可见的工作。

【讨论】:

    【解决方案4】:

    使用 AlarmManager 来完成这项任务似乎很乏味。只需将另一个变量添加到您的 SharedPreferences。存储上次更新计数器的时间。(可能 - Calendar.getInstance().getTimeInMillis())

    因此,当您在获取计数器值的同时打开片段时,您必须获取上次更新的时间。对照当前日期检查存储的时间。如果不匹配,则重置计数器值。

    如果我确实错过了什么,请告诉我..:)

    【讨论】:

    • 您错过了这样一个事实,即屏幕可以在 23:59:59 开启,而计数器将在下一秒保持不变,而此时它们应该被重置。否则,我也同意,拥有一个 AlarmManager、Service、BroadcastReceiver 有很多矫枉过正。
    【解决方案5】:

    一些建议:

    1.

    COUNT_OOL = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("oolongCount", 0);
    COUNT_WTE = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("whiteCount", 0);
    COUNT_BLO = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("bloomingCount", 0);
    COUNT_BLK = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("blackCount", 0);
    COUNT_HBL = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("herbalCount", 0);
    COUNT_GRN = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("greenCount", 0);
    COUNT_MTE = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE).getInt("mateCount", 0);
    

    应该这样编辑

    private SharedPreferences sharedPreferences;
    sharedPreferences = getActivity().getSharedPreferences("keyname", Context.MODE_PRIVATE);
    COUNT_OOL = sharedPreferences.getInt("oolongCount", 0);
    

    1. 根据规范的需要命名

    2. 我觉得你的代码问题是写的比较乱,整理的先看看吧,你先看看,我现在写一下,顺便说一下。也许你应该使用android系统的时钟。

    【讨论】:

    • 它没有回答问题,即使你说的完全正确。
    猜你喜欢
    • 1970-01-01
    • 2019-05-26
    • 2018-02-02
    • 2015-10-03
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多