简体   繁体   中英

How to signal to a fragment that an async task has not finished its task

In a fragment I want to prevent the user to start another task while the async task is not completed.

So I have a global variable (counter) that I use to signal a value back to the fragment. The async task starts and every second onProgressUpdate calls the method (setVal) to send the value of the counter to the fragment. I receive the counter in the fragment. It has the right value but each time I try to access it in the button btn1 its value is always 0.

Why is that? What is the right way to do what I want?

fragment:

public class Frag1 extends android.app.Fragment {
    private static TextView txt;
    private static View view;
    private int counter;

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = null;
        view = inflater.inflate(R.layout.fragment_frag1, container, false);
        return view;
    }

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

        txt = (TextView) getActivity().findViewById(R.id.txt);
        Button btn = (Button) getActivity().findViewById(R.id.btn1);
        btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Log.i("Frag1","val: "+counter);
                if(counter > 0) return;
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                Frag2 f2 = new Frag2();
                ft.replace(R.id.content_frame, f2);
                ft.addToBackStack("f2");
                ft.commit();
            }
        });

        Button btn2 = (Button) getActivity().findViewById(R.id.btn2);
        btn2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                AsyncCounter ac = new AsyncCounter(counter);
                ac.execute();
            }
        });

    }

    void setVal(int i){
        counter = i;
    }

}

Async task:

class AsyncCounter extends AsyncTask<Void, Integer, Void> {
    private int cnt;
    private  Frag1 f1 = new Frag1();

    public AsyncCounter(int counter) {
        cnt = counter;
    }

    @Override
    protected  Void doInBackground(Void... params) {
        for(int i=0;i<60;i++){
            publishProgress(i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        Log.i("ASYNC TASK","val: "+values[0]);
        cnt = values[0];
        f1.setVal(cnt);
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
    }

}

So you don't have a global variable. You have an instance variable. Instance variables are replicated for each object you create from the class where you declared those variables, so that each object can have its own state, separated and independently managed from the state of other objects of the same class.

It turns out you have many fragment objects. One that is created by the system or by your activity code, showing its view on the screen. And the many you create in the task class, one for each time the onProgressUpdate method is called.

Remember the bit about the "separated and independently managed" state of the objects created from a single class? You see it at work here: the original fragment, the one you see on the screen, always keeps its counter's original value, the value it started with. The task updates the counter's value of the fragments it creates; and each counter is incremented only one time, because the task creates a new fragment each time it wants to update the counter.

To do what you want, you need to pass to the task a reference to the original fragment, eg as argument in the task's constructor. Then, use that reference to update the counter in onProgressUpdate .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM