1

私のアプリケーションでは、ハンドラーを使用して、ランダム化された時間の後にランナブルを実行するサービスがあります。プログラムは正常に動作します - 数時間です。突然、プログラムは次のトレースで nullpointerexception をスローします。

java.lang.NullPointerException
at com.martin.ontime.OnTimeService$2.run(OnTimeService.java:224)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

さらに、アプリの強制終了後すぐにアプリを再起動できますが、例外はさらに数時間スローされません。ハンドラーに関する省略コードは次のとおりです。

public class AppService extends Service{

 /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 INITIATE ALL THE GLOBAL VARIABLES

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/

 //Handler that times the processes
 private Handler h = new Handler();

 /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/







 /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    EXECUTE ALL CREATE FUNCTIONS

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/

 @Override
 public void onCreate(){

  super.onCreate();

  //Clear all timers
  h.removeCallbacks(setTime);
  h.removeCallbacks(setAuto);

  //Set a timer to start the processes
  h.postDelayed(setAuto, 0);

 }

 /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/    







 /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    EXECUTE THESE FUNCTIONS WHEN SERVICE IS STOPPED

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/     

 @Override
 public void onDestroy(){

  //Clear all timers
  h.removeCallbacks(setTime);
  h.removeCallbacks(setAuto);

 }

    /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/     





 /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    HANDLER RUNNABLE

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/     

 //Runnable
 private Runnable setAuto = new Runnable() {

  public void run(){

   //Create a random number generator
   Random r = new Random();

   //Determine a random amount of time until time is changed
   long d = r.nextInt(5) * 60 * 1000;

   //Wait
   h.postDelayed(setTime, d);

  }

 };

 //Runnable used to set a random allowance
 private Runnable setTime = new Runnable() {

  public void run(){

   try {

    //Create a random number generator
    Random r = new Random();

    //Determine a random amount of time until time is changed
    long d = r.nextInt(30) * 60 * 1000 + 1800000;

    //Wait
    h.postDelayed(setAuto, d);

                           ***TRY/CATCH SURROUNDS A DATA OUTPUT STREAM***

   }

   catch (IOException e){

    e.printStackTrace();

   }

  }

 };

    /**XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/    
}

サービスにこの問題があると思われる別のプログラムがあります。ハンドラーとランナブルに関係し、両方のプログラムで共有されるコードのみをコピーしました。これがこの問題を解決するのに十分な情報であることを願っています. さらに情報が必要な場合は、必ずいくつかの空白を埋めます。これらと私の将来のアプリにとって大きな助けになるでしょう!

4

1 に答える 1

0

特定の条件下でのみランナブルをインスタンス化し、特定の条件下でのみ postDelayed を実際に実行しているため、非常によく似た問題がありました。例えば

if (conditions){
  myRunnable = new Runnable(){
    @Override
    public void run(){
    }
  }
 myHandler.postDelayed(myRunnable, 1000*60*1);
}
@Override
public void onDestroy(){
myHandler.removeCallbacks
}

これにより強制終了が発生しないようにするために、次のように変更しました

@Override
public void onDestroy(){
try {
if (conditions)
myHandler.removeCallbacks;
} catch (Exception e){//do nothing
 }

これで、誤って削除コールバックが誤って呼び出された場合、例外がキャッチされ、強制的に閉じられなくなりました。

おそらく、特定の条件が満たされていないために postDelayed が実行されていなかったか、postDelayed が開始される前に、システムがサービスを破棄し、ondestroy の removecallbacks が呼び出された可能性があります。したがって、それを try ブロックに入れた場合、removecallbacks はまだ失敗する可能性がありますが、ユーザーに影響を与えることはありません。

これが8か月前に尋ねられたことは知っていますが、私の答えが他の誰かに役立つかもしれないと思いました. :) お役に立てれば。

于 2011-07-30T06:10:04.700 に答える