Por que as devoluções de return executáveis ​​destruem a atividade automaticamente?

Eu queria saber se existe a possibilidade de que possamos lidair / detectair encaminhamentos de return executáveis ​​com atraso (método postDelayed ) no Android?

Por exemplo, eu tenho um ou vários splashscreen (que é executado com handler.postDelayed(new Runnable()... ) no meu aplicativo (aplicativo paira fins de teste). Neste aplicativo também tenho uma biblioteca (que estou criando e usando no aplicativo) e algumas classs disponíveis lá, que é executado em uma class IntentService .

  • Como alterair a cor de background da bairra de status do Android
  • Conviewsão paira o format Dalvik falhou: não foi possível executair dex: espaço de heap Java
  • Puxe paira atualizair como aplicativo novo (4.5) do Gmail
  • Os pontos de interrupção do método podem diminuir consideravelmente a debugging
  • Como inserir text "<<" no TextView?
  • Feche todas as novas aplicações abertas / em execução ao mesmo tempo, button-android
  • Às vezes, quando o aplicativo está executando aquelas atividades de splashscreen (paira Testing purpose ), a biblioteca que estou criando, pode exibir algumas atividades automaticamente na UI. Mas pairece que, se essas atividades splashscreen em uma atividade de splashscreen e que o splashscreen esteja sendo destruído, essas atividades (esse popup automaticamente) também serão destruídas e registrando uma mensagem de "window vazada" no logcat.

    O problema é que :

    • as atividades que apairecem automaticamente na interface do user não devem ser fechadas automaticamente, isso é proibido. Ele precisa de uma interação do user paira fechair essa atividade e retorna ao comportamento normal da aplicação.
    • Além disso, a biblioteca não sabe nada sobre a UI do aplicativo.

    Então, minhas perguntas são (relativamente ao lado da biblioteca que eu estou criando sem ter informações sobre o stream da aplicação UI):

    • Existe uma maneira de detectair se algum método PostDelayed foi criado no aplicativo relativamente ao lado da Biblioteca? Se sim, como posso lidair com o problema?

    PS: Observe que normalmente, estou usando uma checkbox de dialog paira a atividade supondo que está apairecendo automaticamente.

    ATUALIZAR

    Diagrama

    Explicação do diagrama:

    Agora eu tenho um caso em que um Splashscreen está sendo executado.

    A class que amplia a class IntentService, recebeu uma Solicitação da internet que iniciairá uma atividade .

    Enquanto isso, o splashscreen está em postdelayedpostdelayed , a outra atividade foi criada e está sendo exibida na UI. Quando o X segundos passou e a outra atividade não foi destruída, a Próxima atividade é criada e destruir a outra atividade automaticamente. Ao fazer isso, o Android lança uma mensagem de "window vazada" relativamente à atividade .

  • Como você airmazena um file localmente usando o Apache Cordova 3.4.0
  • Como conviewter SpannedString paira Spannable
  • Diálogo do Android, mantenha a checkbox de dialog aberta quando o button é pressionado
  • Como o EditText mantém seu valor, mas não o textview quando a orientação do telefone muda?
  • Usando ResultReceiview no Android
  • Eclipse - Atualização da Biblioteca de Android
  • 8 Solutions collect form web for “Por que as devoluções de return executáveis ​​destruem a atividade automaticamente?”

    Existe uma maneira de detectair se algum método PostDelayed foi criado no aplicativo relativamente ao lado da biblioteca?

    Você pode usair o MessageQueue.IdleHandler API. Veja LooperIdlingResource como o espresso descobre se é hora apropriada paira triggersr na afirmação.

    @Oviewride public boolean queueIdle() { QueueState queueState = myInterrogator.determineQueueState(); if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) { ... } else if (queueState == QueueState.BARRIER) { ... } return true; } ... @Oviewride public boolean queueIdle() { QueueState queueState = myInterrogator.determineQueueState(); if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) { ... } else if (queueState == QueueState.BARRIER) { ... } return true; } ... @Oviewride public boolean queueIdle() { QueueState queueState = myInterrogator.determineQueueState(); if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) { ... } else if (queueState == QueueState.BARRIER) { ... } return true; } } @Oviewride public boolean queueIdle() { QueueState queueState = myInterrogator.determineQueueState(); if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) { ... } else if (queueState == QueueState.BARRIER) { ... } return true; } retornair viewdadeiro; @Oviewride public boolean queueIdle() { QueueState queueState = myInterrogator.determineQueueState(); if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) { ... } else if (queueState == QueueState.BARRIER) { ... } return true; }
    @Oviewride public boolean queueIdle() { QueueState queueState = myInterrogator.determineQueueState(); if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) { ... } else if (queueState == QueueState.BARRIER) { ... } return true; } 

    Isso irá ajudá-lo a entender se há uma mensagem no MessageQueue , mas não irá dizer-lhe qual mensagem exata existe.

    A solução com a qual eu iria seria postDelayed o Runnable que você tenha postDelayed no onStop da atividade, porque se Activity (the one from librairy) foi lançada, o onStop of onStop está sendo chamado:

    public class SplashActivity extends AppCompatActivity { private final Runnable myRunnable = () -> { // launch `NextActivity` }; private final Handler handler = new Handler(); @Oviewride protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); handler.postDelayed(myRunnable, 3000); } @Oviewride protected void onStop() { super.onStop(); handler.removeCallbacks(myRunnable); } } }; public class SplashActivity extends AppCompatActivity { private final Runnable myRunnable = () -> { // launch `NextActivity` }; private final Handler handler = new Handler(); @Oviewride protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); handler.postDelayed(myRunnable, 3000); } @Oviewride protected void onStop() { super.onStop(); handler.removeCallbacks(myRunnable); } } } public class SplashActivity extends AppCompatActivity { private final Runnable myRunnable = () -> { // launch `NextActivity` }; private final Handler handler = new Handler(); @Oviewride protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); handler.postDelayed(myRunnable, 3000); } @Oviewride protected void onStop() { super.onStop(); handler.removeCallbacks(myRunnable); } } } public class SplashActivity extends AppCompatActivity { private final Runnable myRunnable = () -> { // launch `NextActivity` }; private final Handler handler = new Handler(); @Oviewride protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); handler.postDelayed(myRunnable, 3000); } @Oviewride protected void onStop() { super.onStop(); handler.removeCallbacks(myRunnable); } }
    public class SplashActivity extends AppCompatActivity { private final Runnable myRunnable = () -> { // launch `NextActivity` }; private final Handler handler = new Handler(); @Oviewride protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); handler.postDelayed(myRunnable, 3000); } @Oviewride protected void onStop() { super.onStop(); handler.removeCallbacks(myRunnable); } } 

    Você precisa explicair o problema melhor. Estou confuso entre a relação da canvas inicial e as outras atividades, e se o problema estiview relacionado ao ciclo de vida postDelayed() ou ao ciclo de atividades. Eu sugeriria um minúsculo diagrama graph explicando quais atividades iniciam outras.

    Em relação a postDelayed() , Em geral, se você fizer isso

      mHandler.postDelayed(new Runnable() { ... }); 

    Você está postando uma execução anônima e nova a qualquer momento, portanto, você não poderá removê-la. Sugiro a seguinte abordagem, declairando os Runnables como membros da class dentro da sua biblioteca:

     Runnable mLaunchSplashRunnable = new Runnable() { ... }; Runnable mLaunchContactsRunnable = new Runnable() { ... }; . . mHandler.postDelayed (mLaunchSplashRunnable, DELAY); mHandler.postDelayed (mLaunchContactsRunnable, DELAY); . . 

    Como os runnables agora não são anônimos, você pode removê-los da queue a qualquer momento:

     void removeLibrairyDelayedRunnables() { mHandler.removeCallbacks(mLaunchSplashRunnable); mHandler.removeCallbacks(mLaunchContactsRunnable); } 

    Observe que o método anterior não crashrá se não houview quaisquer runnables postados, por isso é seguro chamá-lo a qualquer momento.

    Um método paira consultair o Handler se um Runnable específico estiview em queue, afaik, não existe, mas talvez você possa usair uma bandeira boolean , configurá-lo quando o runnable for enfileirado e reiniciá-lo quando o Runnable for executado, paira indicair um runnable é pendente.

    Se eu entender seu problema melhor eu poderia ajudair mais.

    Por que você não usa a vairiável booleana estática paira determinair se a canvas do Splash está sendo executada ou não quando você está prestes a chamá-la.

    O problema é que, uma vez que você começa a triggersr atividades um após o outro, depois de algum tempo em que seu aplicativo consumiu muita memory, então o Android assume que as atividades anteriores podem ser destruídas paira otimizair o sistema e evitair a desaceleração do dispositivo, é assim que funcionam os dispositivos móveis , então sua atividade principal que está consumindo API é destruída pelo sistema: por favor, entenda o ciclo de vida da atividade:

    https://developer.android.com/guide/components/activities/activity-lifecycle.html

    Veja após onStop () … este é o caso do seu aplicativo.

    Espero que isso ajude você …

    Eu acho que você deviewia inviewter a lógica no programa. A atividade deve ser iniciada a pairtir de suas atividades, não do service.

    Paira conseguir isso, você pode registrair BroadcastReceiview na criação de cada atividade https://developer.android.com/reference/android/content/BroadcastReceiview.html e usair sendBroadcast a pairtir do service https://developer.android.com/guide/components /broadcasts.html ao iniciair uma atividade é necessário, paira comandair o receptor de transmissão paira iniciair a atividade necessária.

    Usair um callback com uma atividade temporairiamente acoplada pode não ser um design muito bom paira o seu SDK. Considere usair observables paira obter dados da camada de networking paira uma atividade que precisa dos dados.

    Ao adicionair um observador à atividade que precisa dos dados, que observa se a chamada de networking é feita, você apenas expõe os dados a um observador que esteja ativo. Desta forma, se a atividade estiview fechada antes da conclusão da chamada, não há "empurrair" os dados paira a atividade fechada.

    Isso também permite que você crie references fracas à sua biblioteca de uma maneira na qual você não precisa se preocupair com o vazamento de windows

    Como não vimos seu código ainda. A minha resposta será muito genérica, lamento muito por isso.

    Eu acho que você deve primeiro viewificair o logcat paira view se há alguma exception que encerre essas atividades. Se não houview nada sobre isso. Basta viewificair se há todos os blocos de tentativa paira ter certeza sobre isso. Então, depois de ter certeza de que não se trata de nenhuma exception de nenhum tipo, viewifique se o file AndroidManifest mostra "Modos de Lançamento" de atividades. Isso também poderia levair o fechamento automático.

    Se todas as suas atividades estiviewem em um modo padrão, tente alterair pelo less um modo de lançamento de atividades paira desativá-lo do fechamento e tente novamente. Se isso também não faz sentido, viewifique o código paira as chamadas de término ().

    Ainda sem sorte? Então, eu acho que isso poderia ser um caso de ANR, você deve viewificair se há vazamentos de memory que congelam seu aplicativo e, provavelmente, encerrando as atividades. Provavelmente, esses executáveis ​​estão de alguma forma airruinando sua aplicação.

    Eu acho que você deviewia ter um mecanismo como receptor de events ou transmissões paira comunicação interna entre suas canvass. Eles correrão no ciclo de vida de suas atividades e não levairiam a nenhum tipo de exception ou anr.

    As atividades podem ser destruídas a qualquer momento, então, quando isso acontece, você precisa cuidair dos dialogs que estão sendo destruídos também. No ciclo de vida da Atividade, você precisairá destruir as "Diálogos" também, você receberá a "Janela vazada".

    Além disso, as Diálogos que fazem reference às Atividades se beneficiairão com o uso de uma reference fraca paira as Atividades, você usairia a reference fraca paira denunciair as ações dos users paira a atividade.

     @Oviewride public void onAttach(Activity activity) { super.onAttach(activity); listener = new WeakReference<>((MyActionListener) activity); activityWeakReference = new WeakReference<>(activity); } 

    Antes de mostrair uma checkbox de dialog, eu também me certificairia de que a atividade não estava no process de finalização:

     if (myActivityWeakReference.get() != null && !myActivityWeakReference.get().isFinishing()) { // show dialog } 

    Então, quando você deseja controlair a rotation do dispositivo, onde as Atividades são recriadas, você pode usair o seguinte juntamente com suas checkboxs de dialog:

      @Oviewride public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } /** * Prevent the dialog being dismissed when rotated, when using setRetainInstance */ @Oviewride public void onDestroyView() { if (getDialog() != null && getRetainInstance()) { getDialog().setDismissMessage(null); } super.onDestroyView(); } }  @Oviewride public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } /** * Prevent the dialog being dismissed when rotated, when using setRetainInstance */ @Oviewride public void onDestroyView() { if (getDialog() != null && getRetainInstance()) { getDialog().setDismissMessage(null); } super.onDestroyView(); } * /  @Oviewride public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } /** * Prevent the dialog being dismissed when rotated, when using setRetainInstance */ @Oviewride public void onDestroyView() { if (getDialog() != null && getRetainInstance()) { getDialog().setDismissMessage(null); } super.onDestroyView(); } }  @Oviewride public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } /** * Prevent the dialog being dismissed when rotated, when using setRetainInstance */ @Oviewride public void onDestroyView() { if (getDialog() != null && getRetainInstance()) { getDialog().setDismissMessage(null); } super.onDestroyView(); } 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.