指定的子项已有父项。您必须首先在孩子的父母上调用removeView()

时间:2014-05-15 07:12:13

标签: android dialog singleton

我创建了一个单例辅助类,用于创建我需要在我的应用程序中使用的对话框。

该课程如下:

public class DialogHelper {

private static final String TAG = DialogHelper.class.getSimpleName();
public static final int CHOOSE_COUNTRY_DIALOG = 1;
public static final int DISTANCE_UNIT_DIALOG = 2;
public static final int COUPON_DIALOG = 3;
public static final int VERSION_DIALOG = 4;

private static DialogHelper instance = null;
private AlertDialog.Builder builder;
private AlertDialog dialog;
private ListView dialogList;

private static Activity activity;
private Context context;

private DialogHelper(Context context) {
    CupsLog.d(TAG, "DialogHelper()");
    this.context = context;
    this.activity = (Activity) context;
    builder = new AlertDialog.Builder(context);
    dialogList = new ListView(context);
}

public static DialogHelper getInstance(Context context) {
    if (instance == null) {
        instance = new DialogHelper(context);
    }
    else
    {
        activity = (Activity)context;
    }
    return instance;
}

public AlertDialog getAlertDialog(int dialogType)
{
    switch (dialogType)
    {
        case CHOOSE_COUNTRY_DIALOG:
        {
            builder.setTitle(R.string.choose_country_title_string);
            configureDialogListView(dialogType);
            builder.setView(dialogList);
            break;
        }
        case DISTANCE_UNIT_DIALOG:
        {
            builder.setTitle(R.string.distance_units_string);
            configureDialogListView(dialogType);
            builder.setView(dialogList);
            break;
        }
        case COUPON_DIALOG:
        {
            builder.setTitle(activity.getResources().getString(R.string.coupon_dialog_title));
            final EditText input = new EditText(activity);
            builder.setView(input);
            builder.setPositiveButton(R.string.ok_string, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    Editable value = input.getText();
                    AsyncHttpClient client = new AsyncHttpClient();
                    client.setCookieStore(CookieUtil.getInstance(activity).getPersistentCookieStore());

                    CupsLog.d(TAG, "promotion url " + Consts.stringUri("/account/promotion?code=" + Uri.encode(value.toString())));
                    client.post(Consts.stringUri("/account/promotion?code=" + Uri.encode(value.toString())), new JsonHttpResponseHandler() {

                        @Override
                        public void onSuccess(int arg0, JSONObject arg1) {
                            CupsLog.d(TAG, "onSuccess(int arg0, JSONObject arg1)");
                    /*String title = null;*/
                            String msg = null;
                            try {
                                CupsLog.d(TAG, "promotion response JSON: " + arg1.toString(3));
                                msg = arg1.getString("msg");
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            if (/*title != null && */msg != null) {
                                AlertDialog.Builder response = new AlertDialog.Builder(activity);
                                //response.setTitle(title);
                                response.setMessage(msg);
                                response.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        AccountService.getInstance(activity).pullAccountDetailsFromServer();
                                    }
                                });
                                response.show();
                            }
                        }

                        @Override
                        public void onFailure(Throwable arg0, JSONObject arg1) {
                            CupsLog.d(TAG, "onFailure(Throwable arg0, JSONObject arg1)");
                            String msg = null;
                            try {
                                CupsLog.d(TAG, "promotion response JSON: " + arg1.toString(3));
                                msg = arg1.getString("msg");
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            if (/*title != null && */msg != null) {
                                AlertDialog.Builder response = new AlertDialog.Builder(activity);
                                //response.setTitle(title);
                                response.setMessage(msg);
                                response.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {}
                                });
                                response.show();
                            }
                            super.onFailure(arg0, arg1);
                        }
                    });
                }
            });
            break;
        }
    }

    builder.setNegativeButton(activity.getResources().getString(R.string.close), new android.content.DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });

    dialog = builder.create();
    if (dialogType == COUPON_DIALOG)
    {
        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }
    return dialog;
}

private void configureDialogListView(int dialogType)
{
    dialogList.removeAllViewsInLayout();
    switch (dialogType)
    {
        case CHOOSE_COUNTRY_DIALOG:
        {
            dialogList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int arg2, long arg3) {
                    String chosenUnit = ((TextView) view).getText().toString();
                    String countryString;
                    if (chosenUnit.equals(activity.getResources().getString(R.string.israel_string))) {
                        countryString = "il";
                    } else {
                        countryString = "us";
                    }
                    dialog.dismiss();
                    ((LoginActivity)activity).onCountryFound(countryString);
                }
            });
            String[] stringArray = new String[]{activity.getResources().getString(R.string.usa_string), activity.getResources().getString(R.string.israel_string)};
            ArrayAdapter<String> modeAdapter = new ArrayAdapter<String>(activity, android.R.layout.simple_list_item_1, android.R.id.text1, stringArray);
            dialogList.setAdapter(modeAdapter);
            break;
        }
        case DISTANCE_UNIT_DIALOG:
        {
            dialogList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int arg2, long arg3) {
                    String chosenUnit = ((TextView)view).getText().toString();
                    App.getInstance().isDistanceUnitChanged = true;
                    if (chosenUnit.equals(activity.getResources().getString(R.string.metric_string))){
                        BusProvider.getInstance().post(new DialogChangeEvent(Consts.DISTANCE_UNIT, activity.getResources().getString(R.string.metric_string)));
                        FileAccessUtil.getInstance(activity.getApplicationContext()).setStringProperty(Consts.DISTANCE_UNIT, Consts.DISTANCE_UNIT_KILOMETER);
                    }
                    else {
                        BusProvider.getInstance().post(new DialogChangeEvent(Consts.DISTANCE_UNIT, activity.getResources().getString(R.string.imperial_string)));
                        FileAccessUtil.getInstance(activity.getApplicationContext()).setStringProperty(Consts.DISTANCE_UNIT, Consts.DISTANCE_UNIT_MILE);
                    }
                    dialog.dismiss();
                }
            });
            String[] stringArray = new String[] { activity.getResources().getString(R.string.metric_string), activity.getResources().getString(R.string.imperial_string)};
            ArrayAdapter<String> modeAdapter = new ArrayAdapter<String>(activity, android.R.layout.simple_list_item_1, android.R.id.text1, stringArray);
            dialogList.setAdapter(modeAdapter);
            break;
        }
    }
}
}

现在,为了显示所需的对话框,我使用了这行代码:

DialogHelper.getInstance(this).getAlertDialog(DialogHelper.DISTANCE_UNIT_DIALOG).show();

这一切都很有效,这是第一次。我第二次得到标题中指定的异常。现在,从我之前在这里搜索的问题中我了解到我可能是第一次显示对话框,并且第二次它可能附加到父活动。

问题是:如何在不将其与特定活动紧密耦合的情况下从助手类内部处理这种情况?

2 个答案:

答案 0 :(得分:0)

    Because problem is in instance create
    in your Code

    static DialogHelper storedInstance;
    public static DialogHelper getInstance(Context context) {
       if (instance == null) {
            instance = new DialogHelper(context);
        }
        else
        {

            activity = (Activity)this.context;
        }

        return instance;
    }

    First time you pass Contect and Create dialog successfully with Context but second time you pass second reference context and instance already created so it returns previous context instance.that is problem...
    so 2 way to solve problem
    first Close agove dialog and every time create new Dialog instance
    or
    second is return privois dialog reference like this

    public static DialogHelper getInstance(Context context) {
         if (instance == null) {
            instance = new DialogHelper(context);
            storedInstance=instance ;
        }
        else
        {
           instance=storedInstance;
        }
  return instance;
}

答案 1 :(得分:0)

根据我的理解,我的案例中的问题是我尝试将相同的ListView附加到同一个Dialog构建器,因此创建两个new instance都删除了此错误。所以我所做的是在getAlertDialog方法的开头我添加了这个:

 public AlertDialog getAlertDialog(final int dialogType)
 {
    builder = new AlertDialog.Builder(activity);
    dialogList = new ListView(activity);
    ...