SplashScreen: AsyncTask + ProgressBar + rotate device, Android

2

I have a splashcreen where I run a background process with AsyncTask , when the device is broken the previous task continues, but it starts again.

I am reading about how to face the problem, in the best way possible, that is, avoid bad habits / practices, such as putting the activity in persistent mode or capturing android:configChanges with AndroidManifest , the best method that indicate is to use weakReference but it is not like implementing it with the AsyncTask.

I would also like to show a ProgressDialog but I also find that if the device is broken it disappears.

I'm looking at myself: retaining-objects-across-config-changes

I have the following to do the tests:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private myAsyncTask handlerTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();

                handlerTask = new myAsyncTask();
                handlerTask.execute();

            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    private void largeTask() {

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            //e.printStackTrace();

        }

    }


    private class myAsyncTask extends AsyncTask<Void, Integer, Boolean> {


        @Override
        protected Boolean doInBackground(Void... params) {
            //Log.i(TAG, "doInBackground: ");
            for (int i = 1; i <= 10; i++) {
                largeTask();
                Log.d(TAG, "doInBackground: " + i);
                publishProgress(i * 10);

                if (isCancelled()) {
                    Log.w(TAG, "isCancelled:  TRUE");
                    break;
                }

            }

            return true;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            //Log.i(TAG, "onProgressUpdate: ");
            int progreso = values[0];
            Log.d(TAG, "onProgressUpdate: " + values[0]);
        }

        @Override
        protected void onPreExecute() {
            Log.i(TAG, "onPreExecute: ");
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.i(TAG, "onPostExecute: ");

            if (result) {
                //pDialog.dismiss();
                Toast.makeText(MainActivity.this, "Tarea finalizada!", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        protected void onCancelled() {
            Log.w(TAG, "onCancelled: ");
            Toast.makeText(MainActivity.this, "Tarea cancelada!", Toast.LENGTH_SHORT).show();
        }

    }


}

Each time you press the fabButton you execute the task, if you rotate the device and press again the fabButton launches another task, if you were in onCreate just rotate it would launch again, is what I want avoid, also add a dialogFragment with horizontal progress.

    
asked by Webserveis 06.09.2016 в 20:15
source

1 answer

1

Following the article Handling Configuration Changes with Fragments and adapting to to use the support libraries.

The method that comments is to create a AsyncTask that extends from a Fragment and in SplashScreen implement the methods of AsyncTask

To prevent the task from being re-launched when the device is rotated, it is checked if the fragment is loaded in memory, only one is created again the first time.

Create TaskFragment.java

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;

public class TaskFragment extends Fragment {

    interface TaskCallbacks {
        void onPreExecute();
        void onProgressUpdate(int percent);
        void onCancelled();
        void onPostExecute();
    }

    private TaskCallbacks mCallbacks;
    private DummyTask mTask;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if (context instanceof Activity){
            mCallbacks = (TaskCallbacks) (Activity) context;
        }

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Retain this fragment across configuration changes.
        setRetainInstance(true);

        // Create and execute the background task.
        mTask = new DummyTask();
        mTask.execute();
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;
    }

    private class DummyTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected void onPreExecute() {
            if (mCallbacks != null) {
                mCallbacks.onPreExecute();
            }
        }

        @Override
        protected Void doInBackground(Void... ignore) {
            for (int i = 0; !isCancelled() && i <= 100; i++) {
                SystemClock.sleep(500);
                publishProgress(i);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... percent) {
            if (mCallbacks != null) {
                mCallbacks.onProgressUpdate(percent[0]);
            }
        }

        @Override
        protected void onCancelled() {
            if (mCallbacks != null) {
                mCallbacks.onCancelled();
            }
        }

        @Override
        protected void onPostExecute(Void ignore) {
            if (mCallbacks != null) {
                mCallbacks.onPostExecute();
            }
        }
    }
}

SplashScreen.java

import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements TaskFragment.TaskCallbacks {

    private static final String TAG_TASK_FRAGMENT = "task_fragment";
    private static final String TAG = MainActivity.class.getSimpleName();
    private TaskFragment mTaskFragment;

    private  TextView labelProgress;


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

        FragmentManager fm = getSupportFragmentManager();
        mTaskFragment = (TaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);

        // If the Fragment is non-null, then it is currently being
        // retained across a configuration change.
        if (mTaskFragment == null) {
            mTaskFragment = new TaskFragment();
            fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit();
        }

        labelProgress = (TextView) findViewById(R.id.label_progress);

    }

    @Override
    public void onPreExecute() {
        Log.i(TAG, "onPreExecute: ");
    }

    @Override
    public void onProgressUpdate(int value) {
        value = value;
        Log.d(TAG, "onProgressUpdate: " + String.valueOf(value));
        labelProgress.setText( String.valueOf(value) + "%");

    }

    @Override
    public void onCancelled() {
        Log.i(TAG, "onCancelled: ");
    }

    @Override
    public void onPostExecute() {
        Log.i(TAG, "onPostExecute: ");
    }
}

Version with progressBar

To add a progressBar

In the layout.xml

<TextView
    android:id="@+id/label_progress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="Hello World!" />

<ProgressBar
    android:id="@+id/progress_bar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@+id/label_progress"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="21dp" />

SplashScreen.java

public class MainActivity extends AppCompatActivity implements TaskFragment.TaskCallbacks {

    private static final String TAG_TASK_FRAGMENT = "task_fragment";
    private static final String TAG = MainActivity.class.getSimpleName();
    private TaskFragment mTaskFragment;

    private  TextView labelProgress;
    private ProgressBar mProgressBar;
    private static int oldValue;


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

        FragmentManager fm = getSupportFragmentManager();
        mTaskFragment = (TaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);

        // If the Fragment is non-null, then it is currently being
        // retained across a configuration change.
        if (mTaskFragment == null) {
            mTaskFragment = new TaskFragment();
            fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit();
        }

        labelProgress = (TextView) findViewById(R.id.label_progress);
        mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);

        if (savedInstanceState != null) {
            onProgressUpdate(oldValue);
        }


    }

    @Override
    public void onPreExecute() {
        Log.i(TAG, "onPreExecute: ");
    }

    @Override
    public void onProgressUpdate(int value) {
        value = value;
        Log.d(TAG, "onProgressUpdate: " + String.valueOf(value));
        labelProgress.setText( String.valueOf(value) + "%");
        //mProgressBar.setProgress(value);

        ProgressBarAnimation anim = new ProgressBarAnimation(mProgressBar, oldValue, value);
        anim.setDuration(500);
        mProgressBar.startAnimation(anim);

        oldValue = value;

    }

    @Override
    public void onCancelled() {
        Log.i(TAG, "onCancelled: ");
    }

    @Override
    public void onPostExecute() {
        Log.i(TAG, "onPostExecute: ");
    }


    public class ProgressBarAnimation extends Animation {
        private ProgressBar progressBar;
        private float from;
        private float  to;

        public ProgressBarAnimation(ProgressBar progressBar, float from, float to) {
            super();
            this.progressBar = progressBar;
            this.from = from;
            this.to = to;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            float value = from + (to - from) * interpolatedTime;
            progressBar.setProgress((int) value);
        }

    }

}
    
answered by 06.10.2016 / 10:13
source