2015-04-30 3 views
0

Я обнаружил, что мне нужно позвонить в isDestroyed(), чтобы проверить, не прекращено ли действие. Я сделал это, и все отлично работает.Имитация isDestroyed() в Android

Однако включение isDestroyed() заставляет меня увеличить уровень API Android до уровня (17), с которым мне не удобно. Я бы предпочел не делать этого.

Я думаю, что смогу имитировать isDestroyed() просто переопределив onDestroy() в своей деятельности. Когда этот метод вызывается, я могу просто сохранить этот факт в булевом, а затем использовать его для предоставления моей собственной версии isDestroyed() (меняя название курса).

Будет ли что-то просто, как эта работа? Я вижу много ссылок на onDestroy(), которые не вызываются в некоторых случаях. Есть ли другой способ имитировать это?

+0

Это не будет работать для более ранних уровней api. При этом вы всегда можете использовать аннотацию, чтобы сказать, что эта конкретная часть теста действительна только для уровней api более высокого уровня, а не ниже определенного уровня. Это все равно позволит вам написать тесты для более низких уровней api. –

ответ

0

Это может сработать, в зависимости от того, когда вам нужно проверить isDestroyed().

Если проверить isDestroyed() в Fragment.onDestroy() обратного вызова, моделируемой реализации реализован как вы описываете возвратит false, в то время как Activity.isDestroyed() вернется true. Если вы проверите для isDestroyed() «позже», он будет работать. Вы можете проверить это с помощью следующего тестера приложения:

package com.example.test.myapplication; 

import android.app.Activity; 
import android.app.Fragment; 
import android.os.Handler; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

public class MainActivity extends Activity { 

    private boolean mOnDestroyCalled; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     if (savedInstanceState == null) { 
      getFragmentManager().beginTransaction().add(R.id.container, new MainFragment()) 
        .commit(); 
     } 
    } 

    @Override 
    protected void onDestroy() { 
     mOnDestroyCalled = true; 
     super.onDestroy(); 
    } 

    public boolean isDestroyed_SIMULATED() { 
     return mOnDestroyCalled; 
    } 

    public static class MainFragment extends Fragment { 
     @Override 
     public void onDestroy() { 
      super.onDestroy(); 
      final MainActivity mainActivity = (MainActivity)getActivity(); 
      dumpIsDestroyedImplementations("In Fragment.onDestroy() ", mainActivity); 

      new Handler().postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        dumpIsDestroyedImplementations("A while later   ", mainActivity); 
       } 
      }, 500); 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
      final TextView textView = new TextView(getActivity()); 
      textView.setText("Hello world!"); 
      return textView; 
     } 

     private void dumpIsDestroyedImplementations(String prefix, MainActivity mainActivity) { 
      Log.i("IsDestroyedTest", prefix + "isDestroyed(): " + 
        mainActivity.isDestroyed() + 
        " isDestroyed_SIMULATED(): " + mainActivity.isDestroyed_SIMULATED()); 
     } 
    } 
} 

Если вы запустите это, а затем нажмите кнопку Назад на устройстве, adb logcat -s IsDestroyedTest даст вам следующий вывод:

I/IsDestroyedTest(2143): In Fragment.onDestroy() isDestroyed(): true isDestroyed_SIMULATED(): false 
I/IsDestroyedTest(2143): A while later   isDestroyed(): true isDestroyed_SIMULATED(): true 

Чтобы понять, почему , take a look при реализации isDestroyed().

public boolean isDestroyed() { 
    return mDestroyed; 
} 

... 

final void performDestroy() { 
    mDestroyed = true; 
    ... 
    mFragments.dispatchDestroy(); 
    onDestroy(); 
    ... 
} 

В этом случае, мы можем концептуально переписать следующим образом:

final void performDestroy() { 
    mDestroyed = true; 
    ... 
    MainFragment.onDestroy() // Called by mFragments.dispatchDestroy(); 
    mOnDestroyCalled = true; // From MainActivity.onDestroy() 
    super.onDestroy(); // From MainActivity.onDestroy() 
    ... 
} 

И это легко понять, почему мы получаем выход LogCat мы получаем.

Относительно onDestroy() Не вызываемый иногда, на эту проблему не повлияет симуляция isDestroyed(). И вообще, если это не вызвано, есть веские причины (система срочно нуждается в освобождении памяти и не имеет времени для завершения вызовов жизненного цикла активности, или нет причин для фактического уничтожения активности). Что касается, если есть другие способы имитации этого, по крайней мере, я не могу думать ни о каком.

1

Видя, как рамочный код:

public boolean isDestroyed() { 
    return mDestroyed; 
} 

final void performDestroy() { 
    mDestroyed = true; 
    mWindow.destroy(); 
    mFragments.dispatchDestroy(); 
    onDestroy(); 
    if (mLoaderManager != null) { 
     mLoaderManager.doDestroy(); 
    } 
    if (mVoiceInteractor != null) { 
     mVoiceInteractor.detachActivity(); 
    } 
} 

Я бы сказал, что вы достаточно безопасно использовать свой собственный флаг установлен в onDestroy, вы получите тот же результат, не используя флаг Framework, если только что-то сбои в mWindow.destroy() или mFragments.dispatchDestroy()

Смежные вопросы