0

I'm new to android but based on my understanding that onPostExecute has to run on the main UI thread to be able to access Views and so on which blocks the UI until it finishes. But the application looks ugly -as if it's crashing- when I try to rotate the device while onPostExecute is running (I know it should be a light weight task but I keep in mind slow phones so this might actually happen in my HBO)

Now, here's my code and I know I believe I should use interfaces for communication between my Task, Fragment, and Activity but it's just a proof of concept for now.

//MovieTask Class
public class MovieTask extends AsyncTask<Void, Void, String> {


    private Activity activity;

    public MovieTask(Activity activity) {
        onAttach(activity);
    }

    //should be an interface
    public void onAttach(Activity activit) {
        this.activity = activit;
    }

    //should be an interface
    public void onDetach() {
        this.activity = null;
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        Log.e("ASYNC TASK", "DONE");
        return "DONE: FROM DO TO POST";
    }

    @Override
    protected void onPostExecute(String s) {

        if(this.activity != null)
        {
            ((MainActivity) activity).ShowResult(s);
            Log.e("MovieTask", "Result Received");

        }else
            Log.e("MovieTask", "Activity is null (1)");
    }
}

//My Non-UI Fragment to decouple the Task from the Activity
public class NonUIFragment extends Fragment {

    private MovieTask myTask;
    private Activity activity;



    public NonUIFragment() {
        // Required empty public constructor
    }

    public void BeginTask() {


        if (activity != null) {
            myTask = new MovieTask(activity);
            myTask.execute();
        }
    }

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

        //check that the passed context is an Activity first then,
        if (context instanceof Activity) {
            this.activity = (Activity) context;

            if(myTask != null) {
                myTask.onAttach((Activity) context);
            }
        }
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
setRetainInstance
        setRetainInstance(true);
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if(myTask != null) {
            myTask.onDetach();
    }
}

//Main Activity (Task Consumer)
public class MainActivity extends AppCompatActivity {

    NonUIFragment nonUIFragment;

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

        if (savedInstanceState == null) {
            nonUIFragment = new NonUIFragment();
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(nonUIFragment, "nonUIFragment")
                    .commit();
        }
        else
        {
            nonUIFragment = (NonUIFragment) getSupportFragmentManager().findFragmentByTag("nonUIFragment");
        }

        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                nonUIFragment.BeginTask();
            }
        });
    }


    //should be the consumer interface
    public void ShowResult(String result)
    {
        try {
            Thread.sleep(5000);
            TextView txtVw = (TextView) findViewById(R.id.txtVw);
            txtVw.setText(result);

        } catch (InterruptedException e) {
            Log.e("MovieTask", "mCallbacks is null (2)");

        }
    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        TextView txtVw = (TextView) findViewById(R.id.txtVw);
        String result = txtVw.getText().toString();

        outState.putString("result", result);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        String result = savedInstanceState.getString("result");

        TextView txtVw = (TextView) findViewById(R.id.txtVw);
        txtVw.setText(result);
    }
}

UPDATE 1

In the chat Jigs suggested trying 'runOnUiThread', however onPostExecute already runs on the UI Thread so unfortunately it's kind of irrelevant. I guess what I'm trying to do is not block the UI while the behaviour of onPostExecute is a UI-Blocking in nature which makes it kind of impossible. I'll leave the question around in case anybody has different thoughts!

Mazen Elkashef
  • 3,430
  • 6
  • 44
  • 72
  • what are you trying to update in your onPostExecute() method ? -@IKashef. – Radhey Feb 29 '16 at 12:43
  • @Jig's, For now it's just a simple TextView by calling "((MainActivity) activity).ShowResult(s);" but after I decide the best implementation to over come the -horrible- AsyncTask downsides, it will be updating a ListView with about 20 items worth of movie information. I hope I answered your question properly – Mazen Elkashef Feb 29 '16 at 12:49
  • 1
    @IKashef ,can't getting you properly , lets meet in chat room.. – Radhey Feb 29 '16 at 12:52

0 Answers0