处理Java中延迟事件的最佳方法是什么?

时间:2016-11-14 02:04:44

标签: java android timer timertask

我想在android studio中制作一个简单的游戏,我需要能够推迟某些事件。

我开始做一些谷歌搜索,发现Timer TimerTask似乎是一个不错的选择。但是,如果我的活动调用onPause没有Timer.pause,我必须取消整个内容。

所以,我决定继续创建我自己的类,为我处理事件,并支持暂停。

我创建了一个简单的类(EventHandler),它在users命令上创建“event(s)”,并每10毫秒循环一次事件的ArrayList,以查看System.currentTimeMillis> = {{ 1}}。如果事件完成,则它调用inteface方法,并且事件将自己从ArrayList中删除。

但现在我遇到了一个新问题。

eventFinishedTime在事件结束时调用接口方法(EventHandler),因此我无法在onFinished中使用未声明为final的变量。我能找到的唯一方法就是每次想要推迟一个事件时都要制作一个新方法,这似乎是不好的做法。

所以我的问题是,这样做的最佳方法是什么,或者你会怎么做?

随意询问您是否希望查看我的代码,只需指定哪个部分:) 也可以随意询问更多信息......我总结了很多,并且非常愿意尝试进一步解释,并举例说明。

谢谢!

这是EventHandler.class(我没有包含导入...滚动到底部以查看调用接口方法的位置):

onFinished

这是我尝试使用它的地方(这只是使用int x的一个例子):

public class EventHandler extends Thread {
    //Constants
    final String TAG = "EventHandler";
    final long WAIT_TIME = 10;


    public ArrayList<Event> events = new ArrayList<>(); //Every WAIT_TIME the run() funtion cycles through this list and checks if any events are complete
    public boolean runChecks = true; //If true, the run() function goes (It's only false while the DoDayActivity tells it to pause
    public long pauseStartTime; //This value tags the System.currentTimeMillis() @pauseCheck
    public long totalPausedTime = 0; //This value contains how long the EventHandler was paused
    Activity activity;

    public EventHandler(Activity activity) {
        this.activity = activity;
    }

    public void run() {
        //checking the listeners
        while (true) {
            if (runChecks) {//Making sure the timer isn't paused
                checkListeners();
            }
            try {
                Thread.sleep(WAIT_TIME); //Yes I am using Thread.sleep(), kill me
            } catch (Exception ignore) {
            }
        }

    }

    public interface OnEventListener {
        void onFinished();
    }


    public void createEvent(String name, long milliseconds, OnEventListener eventListener) {//This is how an event is created, see the private Event class below
        new Event(this, name, milliseconds, eventListener);
    }

    public void checkListeners() {
        for (Event event : events) {
            event.amIFinished();//A method that checks if the event has reached its end time
        }
    }

    public void pauseCheck() { //"Pauses" the timer (Probably not the best way, but it is simple and does what I need it to
        runChecks = false;
        pauseStartTime = System.currentTimeMillis();
    }

    public void resumeCheck() {//Resumes the timer by adding the amount of time the EventHandler was paused for to the end if each event
        try {
            if ((pauseStartTime > 99999999)) {//For some reason, when an activity is created, onResume is called, so I added this in there to prevent glicthes
                totalPausedTime = System.currentTimeMillis() - pauseStartTime;
                Log.d(TAG, "Resuming, adding " + String.valueOf(totalPausedTime) + " milliseconds to each event");
                for (Event e : events) {
                    e.end += totalPausedTime;
                }
            }
        } catch (Exception e) {
            Log.w(TAG, "During resume, EventHandler tried to add time to each of the events, but couldn't!");
            e.printStackTrace();
        }

        runChecks = true;

    }


    private class Event { //Here is the class for the event
        public long start;
        public long end;
        OnEventListener listener;
        EventHandler parent;
        String name;

        public Event(EventHandler parent, String name, long milliseconds, OnEventListener listener) {
            start = System.currentTimeMillis();
            end = start + milliseconds;
            this.listener = listener;
            this.parent = parent;
            this.name = name;

            //Adding itself to the ArrayList
            parent.events.add(this);
        }

        public void amIFinished() {//Method that checks if the event is completed
            if (System.currentTimeMillis() >= end) {//Removes itself from the arraylist and calls onFinished
                Log.d(TAG, "Completed " + name);
                parent.events.remove(this);
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        listener.onFinished(); //This is where the interface method is called!
                    }
                }); 
            } 
        }
    }
}

4 个答案:

答案 0 :(得分:1)

这只是需要有效最终的参考;可以从内部类更改对象的状态:

text.getX(), text.getY()

或者......使用lambda

AtomicInteger x = new AtomicInteger(0);

eventHandler = new EventHandler(this);
eventHandler.start();
eventHandler.createEvent("Change X Value", 800, new EventHandler.OnEventListener() {
    @Override
    public void onFinished() {
        // x is effectively final so we can reference it
        x.set(5);
    }
}); 

如果我这样做,我会抽象游戏时间线。在主循环中增加 tick 计数器,并在游戏时间到期时处理事件,而不是实时。

然后可以通过将它们添加到按游戏时间排序的TreeSet来调度事件,然后将它们拉出集合并在主循环到期时执行。

答案 1 :(得分:0)

我不确定你要完成什么,但听起来你可能对ScheduledExecutorService感兴趣。这样,您就可以在将来的特定时间提交RunnablesCallables。事件结束后,他们还会自动从Queue中删除自己。

答案 2 :(得分:0)

这不解决它?这听起来像取消和重新创建TimerTasks来模拟暂停是人们所做的事情:

Pausing/stopping and starting/resuming Java TimerTask continuously?

答案 3 :(得分:0)

由于这是Android,因此您无法确定在onPause调用后您的应用程序未从内存中完全删除。所以最好的方法是使用ScheduledExecutorService之类的东西。 onPause事件发生时取消预定的Runnable。调用onResume时,只需再次安排相同的Runnable。

其他任何可能导致Android应用程序模型出现问题。暂停状态下的应用程序可以从内存中删除。因此,您可能必须为自定义计时器实现保存状态。