Android AsyncTask doInBackground changed in Android7

My application has a snippet with AsyncTask that retrieves records from a database and displays them using a ListView. Works fine for several years, but now on Android 7 it stops, without any entries. However, after exiting the application (for example, switching to the Android settings), then, after that, the entries are displayed. Debugging shows that onPreExecute is executed initially, but doInBackground is not executed until the application exits.

Can anyone suggest what has changed in Android 7, what can explain this?

        // 1. ==== Fragment containing AsyncTask ====

        public class AuditFragment extends ListFragment implements OnClickListener
        {

            // Using beep for debugging until I can get LogCat in Eclipse restored for Android 7 
            public static void beep ( final int times )
            {
                ...
            }

            private class UpdateAuditTask extends AsyncTask<Void, RecordEntry, SQLException>
            {

                @Override
                protected SQLException doInBackground ( Void... parameters )
                {
                    beep ( 5 ); // Debug, in the absence of LogCat
                    ...   
                }

                @Override
                protected void onProgressUpdate ( RecordEntry... values )
                {
                    L.logMethodCall ( (Object[]) values );

                    if ( values.length == 1 )
                        {
                        auditListAdapter.add ( values[0] );
                        auditListAdapter.notifyDataSetChanged ();
                        }
                }

                @Override
                protected void onPreExecute ()
                {
                    L.logMethodCall ();
                    beep ( 2 ); // Debug, in the absence of LogCat
                    auditListAdapter.clear ();
                }

                @Override
                protected void onPostExecute ( SQLException result )
                {
                    L.logMethodCall ( result );
                    ...
                }
            }

            private void updateAuditList ()
            {
                L.logMethodCall ();

                beep (1);  // Debug, in the absence of LogCat

                new UpdateAuditTask ().execute ();
                auditListAdapter.notifyDataSetChanged ();
            }

            public AuditFragment()
            {
            }

            @Override
            public void onClick ( View view )
            {
                ...
            }

            @Override
            public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
            {
                ...
            }

            @Override
            public void onStart ()
            {
                L.logMethodCall ();
                super.onStart ();

                getListView ().setAdapter ( auditListAdapter );
                updateFragmentGui ();
            }

            @Override
            public void onResume ()
            {
                L.logMethodCall ();
                super.onResume ();
                ...
            }

            private void updateFragmentGui ()
            {
                L.logMethodCall ();
                ...
            }

            private class AuditListAdapter extends ArrayAdapter<RecordEntry>
            {
                ...
            }

        }

        // 2. ==== Activity which executes Fragment ====

        public class AuditActivity extends Activity {

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                L.logMethodCall(savedInstanceState);
                setContentView(R.layout.audit);

                // Add "static" fragments
                if (savedInstanceState == null) {
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    AuditFragment audit = new AuditFragment();
                    ft.add(R.id.kstation_audit_audit_frag, audit);
                    ft.commit();
                }
            }

            @Override
            public void finish() {
                super.finish();
                overridePendingTransition(R.anim.donothing, R.anim.collapse_righttoleft);
            }
        }

        // 3. ==== Method in main Activity ====

        public void showAudit() {
                Intent intent = new Intent(C.getActivity(), AuditActivity.class);
                C.getActivity().startActivity(intent);
            }

Samsung SM-T580.
"" onPreExecute, makeInBackground: - "" - "" - ""

, AuditFragment - doInBackground.

: LogCat Android 7 ( sdk Monitor, Eclipse), .

Experiments: - restore updateAuditTask.executeOnExecutor (AsyncTask.THREAD_POOL_EXECUTOR) (instead of using my own executor) and output the THREAD_POOL_EXECUTOR properties to LogCat immediately before calling executeOnExecutor

  • Android 7. Racks, that is, doInBackground is not running.

            THREAD_POOL_EXECUTOR.getCorePoolSize ()  : 4
            THREAD_POOL_EXECUTOR.getMaximumPoolSize(): 17
            THREAD_POOL_EXECUTOR.getPoolSize()       : 4
            THREAD_POOL_EXECUTOR.getActiveCount()    : 4
    
  • Android 6. Does not stop, i.e. doInBackground does.

            THREAD_POOL_EXECUTOR.getCorePoolSize ()  : 5
            THREAD_POOL_EXECUTOR.getMaximumPoolSize(): 9
            THREAD_POOL_EXECUTOR.getPoolSize()       : 5
            THREAD_POOL_EXECUTOR.getActiveCount()    : 5
    

I am puzzled by this: in each case, not only the core pool core threads are currently active; the new task is running on Android6, but not on Android7.

Experiment 2. Disable one AsyncTask that starts earlier. This time, the THREAD_POOL_EXECUTOR properties remain the same as before, but the task does not stop.
  1. Android 7. Doesn't stop, that is, doInBackground does.

            THREAD_POOL_EXECUTOR.getCorePoolSize ()  : 4
            THREAD_POOL_EXECUTOR.getMaximumPoolSize(): 17
            THREAD_POOL_EXECUTOR.getPoolSize()       : 4
            THREAD_POOL_EXECUTOR.getActiveCount()    : 4
    

So, it would seem, the size of the pool, etc. Do not affect the task?

(. , , , , .)

+4
2

AsyncTask.execute() AsyncTask.SERIAL_EXECUTOR, . , Marshmallow AsyncTask 6.0.1.

new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(final Void... voids) {
        Log.d("DERP", "bad task starting");
        try {
            Thread.sleep(5000);
        }
        catch(InterruptedException e) {
            // ignore
        }
        finally {
            Log.d("DERP", "bad task exiting");
        }
        return null;
    }
}.execute();

new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(final Void... voids) {
        Log.d("DERP", "nice task running");
        return null;
    };
}.execute();

:

06-30 15:43:23.777 8761-8792/com.chalcodes.rogueasynctask D/DERP: bad task starting
06-30 15:43:28.777 8761-8792/com.chalcodes.rogueasynctask D/DERP: bad task exiting
06-30 15:43:28.779 8761-9084/com.chalcodes.rogueasynctask D/DERP: nice task running

executeOnExecutor(...) . , , , . AsyncTask setDefaultExecutor, @hide, .

try {
    final Method method = AsyncTask.class.getMethod("setDefaultExecutor", Executor.class);
    method.invoke(null, executor);
} catch(Exception e) {
    Log.e("AsyncTask", "error setting default executor", e);
}

, Android 6 7. , -, AsyncTask, , AsyncTask .

, AsyncTask Android 7. .

0

, . , , , ... : Rx AsyncTask. , .

0

Source: https://habr.com/ru/post/1680234/


All Articles