0

アクティビティの破棄と再作成を行っても、私のアプリケーションに連続値を表示させようとしています。私はバックグラウンドスレッドを使ってFPSを維持しています。基本的にはメッセージをハンドラに送ります。アクティビティが破棄されて再作成されると、新しいハンドラが作成され、バックグラウンドスレッドの新しいインスタンスに送信されます。ただし、メッセージが受信されると、メッセージは「破棄された」アクティビティで実行されている元のハンドラによって受信されているように見えます。私よりも経験豊富な人がこれに重点を置くことができたら本当に感謝します!アクティビティを破棄して再作成するとき、ハンドラは古い破棄されたアクティビティインスタンスでまだ実行中です

マイコード(私はそれの少しより多くがあります知っているが、ほとんどすべての関連のonCreateで起こる):

public class MainActivity extends FragmentActivity { 

final static int UPDATE_DISPLAY = 1; 

//View Pager declarations 
private static final int NUM_PAGES = 4; //Number of viewPager pages 
private ViewPager mPager; 
private ScreenSlidePagerAdapter mPagerAdapter; 
private MainThread thread; 
Fragment[] fragmentMap = new Fragment[NUM_PAGES]; 
//End view pager declarations 

globalData gd; 

private Handler handler = new Handler() 
{ 
    @Override 
    public void handleMessage(Message msg) 
    { 
     //TESTING------------- 
     System.out.println("Received message from background thread."); 
     System.out.println("Handler receiving message is: "+this.toString()); 
     System.out.println("Handler is running in activity: "+MainActivity.this.toString()); 
     //--------------- 

     if (msg.what == UPDATE_DISPLAY){ 
      ((TextView)findViewById(R.id.totalGas)). 
        setText("Gas: "+UnitValuePair.convertNumberToString(gd.getGasOwned())); 
      ((TextView)findViewById(R.id.totalRock)). 
        setText("Rock: "+UnitValuePair.convertNumberToString(gd.getRockOwned())); 
      ((TextView)findViewById(R.id.totalMetal)). 
        setText("Metal: "+UnitValuePair.convertNumberToString(gd.getMetalOwned())); 
     } 
     super.handleMessage(msg); 
    } 
}; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    System.out.println("CREATING MainActivity"); 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_screen_slide); 

    Button resetButton = (Button)findViewById(R.id.resetButton); 
    resetButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      resetData(); 
     } 
    }); 

    //Instantiate ViewPager and PagerAdapter 
    mPager = (ViewPager)findViewById(R.id.pager); 
    mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); 
    mPager.setAdapter(mPagerAdapter); 
    mPager.setOffscreenPageLimit(5); 

    //Attach tablayout to view pager 
    TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs); 
    tabLayout.setupWithViewPager(mPager); 

    //Init variable 
    gd = globalData.getInstance(); 

    //Check if new game, and if so, init all base and actual values 
    Context context = getApplicationContext(); 
    SharedPreferences sharedPref = context.getSharedPreferences(
      getString(R.string.preference_file_key), Context.MODE_PRIVATE); 

    //If first start, then init vals and mark that it has been started in shared preferences 
    boolean startedBefore = sharedPref.getBoolean("startedBefore", false); 
    Log.d("TEST", "Value of startedBefore boolean is:" + Boolean.toString(startedBefore)); 
    if (!startedBefore) 
    { 
     gd.initVals(); 
     gd.storeData(); 
     gd.setNewGame(false); 
     SharedPreferences.Editor editor = sharedPref.edit(); 
     editor.putBoolean("startedBefore", true); 
     editor.commit(); 
    } 
    else 
    { 
     System.out.println("Restoring data"); 
     gd.restoreData(); 
    } 

    //TESTING--------- 
    System.out.println("Handler seen by activity is: "+handler.toString()); 
    System.out.println("New Activity is : "+this.toString()); 
    //-------------------- 

    //Start main update thread 
    thread = new MainThread((ViewGroup)findViewById(R.id.mainContainer), gd, handler, getApplicationContext()); 
    thread.setRunning(true); 
    thread.start(); 
} 

@Override 
public void onPause() 
{ 
    System.out.println("PAUSING MainActivity"); 
    super.onPause(); 
    gd.storeData(); 
} 

@Override 
public void onResume() 
{ 
    super.onResume(); 
    System.out.println("RESUMING MainActivity"); 
} 

@Override 
public void onBackPressed(){ 
    if (mPager.getCurrentItem() == 0){ 
     //If the user is currently looking at the first step, allow the system to handle 
     //back button. Calls finish() on activity and pops the back stack 
     super.onBackPressed(); 
    } else { 
     mPager.setCurrentItem(mPager.getCurrentItem() - 1); 
    } 
} 

public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter 
{ 
    public ScreenSlidePagerAdapter(FragmentManager fm) 
    { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem (int position) 
    { 
     switch (position) { 
      case 0: 
       CreationFragment newFragment0 = CreationFragment.newInstance(0); 
       fragmentMap[0] = newFragment0; 
       return newFragment0; 

      case 1: 
       UniverseFragment newFragment1 = UniverseFragment.newInstance(1); 
       fragmentMap[1] = newFragment1; 
       return newFragment1; 

      default: 
       return ScreenSlidePageFragment.create(position); 
     } 
    } 
    @Override 
    //Provides the titles of the fragments for use in tabLayout 
    public CharSequence getPageTitle(int position) { 
     String title=" "; 
     switch (position){ 
      case 0: 
       title="Create"; 
       break; 
      case 1: 
       title="Universe"; 
       break; 
      case 2: 
       title="Upgrades"; 
       break; 
      case 3: 
       title="Stats"; 
       break; 
     } 

     return title; 
    } 

    @Override 
    public int getCount() 
    { 
     return NUM_PAGES; 
    } 

} 

@Override 
protected void onDestroy(){ 
    System.out.println("DESTROYING MainActivity"); 
    //handler = null; 
    super.onDestroy(); 
} 

public void resetData() 
{ 
    gd.initVals(); 
    gd.setVisibilityChangedDisplay(true); 
    gd.setVisibilityChangedInv(true); 
    gd.setChangedDisplay(true); 
    gd.setChangedInv(true); 
} 

} 

logcat:

元のハンドラ、6402d8eは、で実行してアウトを開始活動108d9af。アクティビティーは、アクティビティー3112cf7として一時停止、破棄、再作成されます。新しいハンドラ、70420f6が作成され、新しいバックグラウンドスレッドに送信されます。バックグラウンドスレッドはメッセージの送信を開始し、受信しますが、受け取ったハンドラは元のスレッド6402d8eであり、アクティビティ108d9afで実行中であることを示します。

04-09 20:17:41.471 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Received message from background thread. 
04-09 20:17:41.471 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler receiving message is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {6402d8e} 
04-09 20:17:41.471 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler is running in activity: [email protected] 
04-09 20:17:41.502 29339-29339/com.kessler.alexi.stellargrowth I/System.out: PAUSING MainActivity 
04-09 20:17:41.502 29339-29339/com.kessler.alexi.stellargrowth D/TEST: Storing data 
04-09 20:17:41.741 29339-29339/com.kessler.alexi.stellargrowth I/System.out: DESTROYING MainActivity 
04-09 20:17:41.759 29339-29339/com.kessler.alexi.stellargrowth I/System.out: CREATING MainActivity 
04-09 20:17:41.759 29339-29339/com.kessler.alexi.stellargrowth W/FragmentManager: moveToState: Fragment state for CreationFragment{a0042e2 #1 id=0x7f0d006d} not updated inline; expected state 1 found 0 
04-09 20:17:41.759 29339-29339/com.kessler.alexi.stellargrowth W/FragmentManager: moveToState: Fragment state for UniverseFragment{66e2681 #2 id=0x7f0d006d} not updated inline; expected state 1 found 0 
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth D/TEST: Value of startedBefore boolean is:true 
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Restoring data 
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth D/TEST: Retrieving data 
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler seen by activity is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {70420f6} 
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: New Activity is : [email protected] 
04-09 20:17:41.775 29339-29339/com.kessler.alexi.stellargrowth I/System.out: New thread created. Handler seen by thread is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {70420f6} 
04-09 20:17:41.805 29339-29339/com.kessler.alexi.stellargrowth I/System.out: RESUMING MainActivity 
04-09 20:17:41.811 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Received message from background thread. 
04-09 20:17:41.811 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler receiving message is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {6402d8e} 
04-09 20:17:41.811 29339-29339/com.kessler.alexi.stellargrowth I/System.out: Handler is running in activity: [email protected] 

---- UPDATE ------ 新しい活動は、新しいスレッドを開始しますが、メッセージを送信する1が破壊されている必要があります古いもののIDを持っている

04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: New Activity is : [email protected] 
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: New thread created with id: 23410 
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Handler seen by new thread is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {cf3308c} 
04-10 10:43:41.149 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Starting thread with id: 23410 
04-10 10:43:41.180 19846-19878/com.kessler.alexi.stellargrowth I/System.out: Thread sending message is: 23405 
04-10 10:43:41.188 19846-19846/com.kessler.alexi.stellargrowth I/System.out: RESUMING MainActivity 
04-10 10:43:41.194 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Received message from background thread. 
04-10 10:43:41.194 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Handler receiving message is: Handler (com.kessler.alexi.stellargrowth.MainActivity$1) {6402d8e} 
04-10 10:43:41.194 19846-19846/com.kessler.alexi.stellargrowth I/System.out: Handler is running in activity: [email protected] 

----- ANSWER ------ それがロックを取得し、基本的に、それは

@Override 
protected void onDestroy(){ 
    System.out.println("DESTROYING MainActivity"); 
    thread.setRunning(false); 
    super.onDestroy(); 
} 

に、以下に示すスレッドの実行コードを、onDestroy変更のちょうど問題だっ判明ブーリアンランニングが自動的に変更されないため、決してシャットダウンしません。新しいスレッドが開始されると、ロックを取得しようとしましたが失敗し、古いものが再び起動しました。

@Override 
public void run() { 
    System.out.println("Thread "+this.getId()+" started."); 
    if (MainThread.lock.tryLock()) { 
     System.out.println("Thread "+this.getId()+" acquired lock"); 
     try { 
      long tickCount = 0L; 
      while (running) { 
       tickCount++; 
       controlFPS(tickCount); 
       update(); 
      } 
     } finally { 
      MainThread.lock.unlock(); 
     } 
    } 
} 
+0

なぜonPause()またはonDestroy()のハンドラ呼び出しを削除しないのですか? – rafsanahmad007

+0

私はあなたが電話を外すことによって何を意味するか分かりません。私はnullにハンドラを設定しようとしましたが、それは何か違いがないようです。 –

答えて

0

それは、クラス内のすべてのメソッドが到達し、できるように、クラスのprivateフィールドとしてスレッドを宣言します。

onDestroy()メソッドでは

を使用

   thread.Abort() 
+0

私はthread.Abort()が有効な構文ではないと思いますが、何も変更しなかったthread.interrupt()を試しました。私が知る限り、新しいスレッドでstartを呼び出すと、古いスレッドが実行されるように設定されます。 –

関連する問題