由片段事务竞争条件导致的容器中的Android重复视图?

时间:2013-03-23 03:38:49

标签: android race-condition fragmenttransaction

我这里有一个简单的程序。当您点击“+”时,它会向列表中添加一个新数字。该列表在屏幕上显示为LinearLayout,其中包含按每个数字标记的按钮。每次按“+”,我清除LinearLayout,然后将每个按钮添加到片段事务并提交它。

因此,如果您在程序启动后按“+”3次,通常会显示如下:

not broken

问题有时似乎是下一个片段事务与前一个事务并发运行。如果你按“+”太快,你会得到一个数字的多个按钮。这就是它的样子:

broken

以下是我的代码的主要部分:

package com.example.kore.ui;

import java.util.LinkedList;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import com.example.kore.R;

public class CodeEditor extends Fragment {
  private LinearLayout fields;
  private final LinkedList<String> list = new LinkedList<String>();
  private int x;
  private boolean sleep;
  private int inits;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.code_editor, container, false);
    fields = (LinearLayout) v.findViewById(R.id.layout_fields);
    ((Button) v.findViewById(R.id.button_clear))
        .setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
            list.clear();
            init();
          }
        });
    ((Button) v.findViewById(R.id.button_new_field))
        .setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            list.add("" + x++);
            init();
          }
        });
    init();
    sleep = true;
    return v;
  }

  private void init() {
    String prefix = "" + inits++;
    fields.removeAllViews();
    FragmentTransaction fragmentTransaction =
        getFragmentManager().beginTransaction();
    for (String s : list) {
      Field f = new Field();
      Bundle b = new Bundle();
      b.putString("X", prefix + " - " + s);
      f.setArguments(b);
      fragmentTransaction.add(R.id.layout_fields, f);
    }
    Log.d("WTF", prefix + " zzzz..");
    if (sleep) {
      try {
        Thread.sleep(2000);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
    sleep = !sleep;
    fragmentTransaction.commit();

  }

}

我每隔一段时间就会调用这个睡眠init,这样可以让它更容易重现。

Field只是一个带有按钮的片段。主要活动只是启动CodeEditor片段。

我刚刚开始编程android。也许有一些我不明白的基础知识。也许事务意味着某种并发性,尽管据我所知,任何地方都不应该有并发性。这种类似种族的行为怎么可能发生?我究竟做错了什么?我将我的按钮包裹在片段中,这些片段被添加到CodeEditor片段中,因为我的真实程序更复杂(这是一个修剪过的示例)所以嵌套片段是有意义的。

完整代码为here

0 个答案:

没有答案