【问题标题】:How to signal to a fragment that an async task has not finished its task如何向片段发出异步任务尚未完成其任务的信号
【发布时间】:2017-11-10 18:02:16
【问题描述】:

在一个片段中,我想阻止用户在异步任务未完成时启动另一个任务。

所以我有一个全局变量(计数器),我用它来向片段发送一个值。异步任务启动,每秒钟 onProgressUpdate 调用方法 (setVal) 将计数器的值发送到片段。我收到片段中的计数器。它具有正确的值,但每次我尝试在按钮 btn1 中访问它时,它的值始终为 0。

这是为什么呢?做我想做的事的正确方法是什么?

片段:

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;
    }

}

异步任务:

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);
    }

}

【问题讨论】:

  • Frag1 f1 = new Frag1(); 在您的 AsyncTask 中不起作用
  • 你为什么这么说?异步任务正在传回正确的值。但是变量的值还是0。

标签: java android android-fragments android-asynctask


【解决方案1】:

所以你没有全局变量。你有一个实例变量。实例变量为您从声明这些变量的类创建的每个对象复制,因此每个对象都可以有自己的状态,与同一类的其他对象的状态分开并独立管理。

原来你有很多片段对象。由系统或您的活动代码创建的一种,在屏幕上显示其视图。还有你在任务类中创建的许多,每次调用onProgressUpdate 方法时都会创建一个。

还记得从单个类创建的对象的“分离和独立管理”状态吗?你在这里看到它在工作:原始片段,你在屏幕上看到的片段,总是保持它的计数器的原始值,它开始时的值。任务更新它创建的片段的计数器值;并且每个计数器只增加一次,因为任务每次想要更新计数器时都会创建一个新片段。

要做你想做的事,你需要将原始片段的引用传递给任务,例如作为任务构造函数中的参数。然后,使用该引用更新onProgressUpdate 中的计数器。

【讨论】:

  • 2分:你第一段就输了我;为什么不是全局变量?从每种方法中都可以看到。我也很快写了这个测试:我不想每次发布一个值时都实例化一个 frag1 引用。但是到了最后一段,你能否更明确一点:如果我将一个参数传递给任务,我该如何更新它以便它对 frag1 可见?
  • @narb 你一定是编程新手,我想。全局通常意味着从代码的每个点都可见,而不仅仅是在单个类中。这确实是一个基本概念。回到正题:你将片段作为参数传递给任务的构造函数;然后,在构造函数中,将该值分配给任务的实例变量。在 onProgressUpdate 中,您在该变量上调用 setVal
  • Giulio,我可以要求快速查看一下我在上面更改的代码。结果相同:该值在 frag1 中显示为正确的值,但计数器值等于 0。
  • @narb 这不是您需要传递给任务的计数器值。您需要传递片段。您不需要在任务中创建新的片段实例,否则您仍然有多个具有不同状态的对象。这是...真的,这是编程中的基本内容。在不得不面对本身复杂的系统(例如 Android 平台)之前,您可能应该先看看这些东西。
  • 我没有将异步任务中的接口和传递片段实例视为基本内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
相关资源
最近更新 更多