如何正确处理Android任务管理器异常处理

时间:2014-05-21 20:00:24

标签: android exception-handling nullpointerexception fatal-error forceclose

我有一个TaskManager,它管理我的应用程序中的几个后台任务但是我不断得到NPE错误并在使用时强制关闭问题(我相信由于我在第108行得到致命异常,即:Log。 v(" TaskManager",task.toString());

我尝试设置一个if语句以防止NPE发生但问题仍然存在我不确定如何在没有NPE / Force Close的情况下如何正常停止。

(非常感谢任何输入/答案/建议)

logcat的:

05-21 19:37:15.540: V/TaskManager(3774): In executeTask() on BACKGROUND THREAD
05-21 19:37:15.630: D/dalvikvm(3774): GC_CONCURRENT freed 373K, 8% free 4845K/5256K, paused 4ms+4ms, total 27ms
05-21 19:37:15.660: V/TaskManager(3774): In logTaskInfo() on BACKGROUND THREAD
05-21 19:37:15.660: V/TaskManager(3774): -------------------
05-21 19:37:15.660: V/TaskManager(3774): Task: PingAliveTask
05-21 19:37:15.660: V/TaskManager(3774): Calling Party: TaskManager
05-21 19:37:15.660: V/TaskManager(3774): Scheduled Start Time: 05/21/2014 19:37:15
05-21 19:37:15.660: V/TaskManager(3774): Actual Start Time: 05/21/2014 19:37:15
05-21 19:37:15.660: V/TaskManager(3774): Ending Time: 05/21/2014 19:37:15
05-21 19:37:15.660: V/TaskManager(3774): Execution Result: true
05-21 19:37:15.660: V/TaskManager(3774): -------------------
05-21 19:37:15.660: V/TaskManager(3774): -------------------
05-21 19:37:15.660: V/TaskManager(3774): In run() on BACKGROUND THREAD
05-21 19:37:15.660: V/TaskManager(3774): In startManaging() on BACKGROUND THREAD
05-21 19:37:15.660: V/TaskManager(3774): In requeue() on BACKGROUND THREAD
05-21 19:37:15.660: V/TaskManager(3774): In sortedInsert() on BACKGROUND THREAD
05-21 19:37:15.660: V/TaskManager(3774): Hoping to sleep : 15 seconds
05-21 19:37:30.660: V/TaskManager(3774): In executeTask() on BACKGROUND THREAD
05-21 19:37:30.740: V/TaskManager(3774): In logTaskInfo() on BACKGROUND THREAD
05-21 19:37:30.740: V/TaskManager(3774): -------------------
05-21 19:37:30.740: W/dalvikvm(3774): threadid=14: thread exiting with uncaught exception (group=0x40dcc930)
05-21 19:37:30.740: E/AndroidRuntime(3774): FATAL EXCEPTION: Thread-250
05-21 19:37:30.740: E/AndroidRuntime(3774): java.lang.NullPointerException: println needs a message
05-21 19:37:30.740: E/AndroidRuntime(3774):     at android.util.Log.println_native(Native Method)
05-21 19:37:30.740: E/AndroidRuntime(3774):     at android.util.Log.v(Log.java:117)
05-21 19:37:30.740: E/AndroidRuntime(3774):     at com.new.project.taskmanager.TaskManager.logTaskInfo(TaskManager.java:108)
05-21 19:37:30.740: E/AndroidRuntime(3774):     at com.new.project.taskmanager.TaskManager.executeTask(TaskManager.java:180)
05-21 19:37:30.740: E/AndroidRuntime(3774):     at com.new.project.taskmanager.TaskManager.startManaging(TaskManager.java:160)
05-21 19:37:30.740: E/AndroidRuntime(3774):     at com.new.project.taskmanager.TaskManager.run(TaskManager.java:240)
05-21 19:37:30.740: E/AndroidRuntime(3774):     at java.lang.Thread.run(Thread.java:856)

来源:

public class TaskManager implements Runnable {

    /** Contains the BackgroundTasks to execute. Will always be sorted on BackgroundTask.startTime */
    private Vector<BackgroundTask> queue;

    /** Task that is executing */
    private BackgroundTask currentTask;

    /** Contains the current states of the system. At current implementation this will be manipulated externally*/
    private Status status;

    /** Controls whether TaskManager continues running*/
    private boolean KILLSWITCH = false;

    /**
     * Signal from outside to stop TaskManager.
     * <p>
     * Testing has concluded that TaskManager will continue execution despite activity ending. In an effort to
     * fix any rogue processes, this mechanism has been created. In onPause() or any other relevant method add
     * {@link TaskManager#KILL()}.
     */
    public void KILL() {
        KILLSWITCH = true;
    }

    /**
     * Takes in no parameters, initializes objects queue and Status
     */
    public TaskManager() {
        initializeQueue();
        status = new Status();

        //TODO remove these for prod
        status.addState(TriggerRule.Offline);
        status.addState(TriggerRule.Online);
        status.addState(TriggerRule.Periodic);
    }


    /**
     * Currently takes in tasks generated from TaskFactory. Other BackgroundTasks can be registered on the queue
     * by using {@link TaskManager#addTask(BackgroundTask)} externally. At this point it is open but the optimal 
     * approach is probably to leave all the tasks in one area, in TaskFactory.
     * @see TaskFactory
     */
    private void initializeQueue() {
        this.logRunningThread("TaskManager", "initializeQueue()");

        queue = new Vector<BackgroundTask>();
        for(String s: TaskFactory.getTaskNameList()) {
            BackgroundTask bgTask = TaskFactory.getTaskByName(s, this); 
            if(bgTask != null) {
                this.sortedInsert(bgTask);
            }
        }
    }

    /**
     * Logs information about task to LogCat
     * @param task - BackgroundTask to print
     */
    private void logTaskInfo(BackgroundTask task) {
        this.logRunningThread("TaskManager", "logTaskInfo()");
        this.logSeparator("TaskManager");

        if (task != null) {
        Log.v("TaskManager", task.toString());
        logSeparator("TaskManager");
        }
        try {
            synchronized(this) {
                this.notify();
            }
        } catch (Exception e) {e.printStackTrace();
        KILL();
        }

    }

    /**
     * Main life cycle of the process. In order to be admitted the BackgroundTask must
     * meet the required rules set. The current state that the rules are tested against
     * are stored in {@link TaskManager#status}.
     * <p>
     * Does the following:
     * <p>
     *  Invokes {@link TaskManager#requeue()} to swap current process back into queue,
     *  grabs next scheduled task and sets {@link TaskManager#currentTask}.
     *  If at or past time to execute, executes {@link TaskManager#currentTask}
     *  else wait until time and execute {@link TaskManager#currentTask}
     */
    private void startManaging() {      

        this.logRunningThread("TaskManager", "startManaging()");

        requeue();

        //look at first entity in queue
            if(! queue.isEmpty()) {
                BackgroundTask t = queue.get(0);

                boolean hasMetRules = RuleBook.validate(status, t.getRule());

                if(hasMetRules) {
                    currentTask = t;

                    queue.remove(t);
                    Time now = new Time();
                    now.setToNow();
                    if(t.getStartTime().before(now)) {
                        executeTask(now);
                    }
                    else {
                        long millis =  t.getStartTime().toMillis(true) - now.toMillis(true);
                        try {
                            synchronized (this) {
                                Log.v("TaskManager", "Hoping to sleep : " + Long.toString(millis / 1000) + " seconds");
                                Thread.sleep(millis);
                            }
                        } catch (Exception e) {e.printStackTrace();}
                        now.setToNow();
                        executeTask(now);
                    }
                }
            }

    }

    /**
     * Uses java.lang.reflect to execute any Background Task no matter the type.
     * This execution is <font color="red"><u><b>blocking</b></u></font>. In other words no further code will execute until 
     * the AsyncTask's status goes to FINISHED.
     * @param now - Recorded time that the process was admitted to processor
     */
    private void executeTask(Time now) {
        this.logRunningThread("TaskManager", "executeTask()");
        currentTask.setActualStartTime(now);
        try {
            currentTask.getTask().getClass().getMethod("execute", Object[].class).invoke(currentTask.getTask(), new Object[] {null}).getClass().getMethod("get").invoke(currentTask.getTask());
        } catch (Exception e) {e.printStackTrace();}

        logTaskInfo(currentTask);
    }


    /**
     * If there is a finished task, it will remove it from the currentTask and place it back into
     * queue with a new start time.
     * @return true if no error during 
     */
    private boolean requeue() {

        this.logRunningThread("TaskManager", "requeue()");

        if(currentTask != null) {

            try {

                BackgroundTask newTask =  TaskFactory.getTaskByName(currentTask.getName(), this);
                sortedInsert(newTask);
                currentTask = null;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * Inserts into the queue at the earliest possible moment
     * <p>
     * RT =  O(n)
     * <p>
     * The queue is sorted based on {@link BackgroundTask#startTime }
     * @param task BackgroundTask to insert into the queue
     */
    private void sortedInsert(BackgroundTask task) {

        logRunningThread("TaskManager", "sortedInsert()");

        for(int i=0; i<queue.size();i++) {
            BackgroundTask t = queue.get(i);
            if(task.compareTo(t) <= 0) {
                queue.insertElementAt(task, i);
                return;
            }
        }
        queue.add(task);
    }


    /**
     * Main loop. Will continue to execute until a signal is received from outside to 
     * stop via {@link TaskManager#KILL()}.
     */
    @Override
    public void run() {
        logSeparator("TaskManager");
        while (! KILLSWITCH) {
            logRunningThread("TaskManager", "run()");
            startManaging();
            logSeparator("TaskManager");
        }
    }


    private void logRunningThread(String tag, String name) {
        if(Looper.myLooper() == Looper.getMainLooper()) {
            Log.v(tag, "In " + name + " on MAIN THREAD");
        }
        else {
            Log.v(tag, "In " + name + " on BACKGROUND THREAD");
        }
    }

    private void logSeparator(String tag) {
        Log.v(tag, "-------------------");
    }

    public void addTask(BackgroundTask t) {
        this.sortedInsert(t);
    }


}

1 个答案:

答案 0 :(得分:0)

可能是task.toString()返回null