Activity中使用Dialog的方式

1.Activity中Dialog的使用方法

        Activity提供了一套Dialog的管理机制,涉及到以下方法。

  1. onCreateDialog: 创建dialog(需要重写)
  2. onPrepareDialog: 在创建dialog后的其他准备工作(需要重写)
  3. showDialog: 显示dialog(直接调用)
  4. dismissDialog: 取消dialog的显示(直接调用)
  5. removeDialog: 去掉该dialog(直接调用)

        先以一个案例来练习下。(此机制已不被推荐使用,但由于ROM定制中有涉及到,所以特此分析下)

public class MainActivity extends Activity {
 
    Button create;
    Button remove;
 
    private static final int TEST_DIALOG = 1;
    private String TAG = "Sun: ";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
 
    private void init() {
        create = (Button) findViewById(R.id.createDialog);
        create.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "showDialog");
                showDialog(TEST_DIALOG);
            }
        });
        remove = (Button) findViewById(R.id.removeDialog);
        remove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "removeDialog");
                removeDialog(TEST_DIALOG);
            }
        });
    }
 
    @Override
    protected Dialog onCreateDialog(int id) {
        Log.d(TAG, "onCreateDialog");
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        AlertDialog dialog = builder.setTitle("Test_Dialog").setIcon(R.mipmap.ic_launcher)
                .setMessage("Test_Message").setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Log.d(TAG, "dismissDialog");
                        dismissDialog(TEST_DIALOG);
                    }
                }).create();
        return dialog;
    }
 
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        Log.d(TAG, "onPrepareDialog");
        super.onPrepareDialog(id, dialog);
    }
}


根据log来看方法的执行:
        (1)先点击createDialog按钮

06-17 12:10:18.353 18470-18470/com.sunjing.myapplication D/Sun:: showDialog
06-17 12:10:18.353 18470-18470/com.sunjing.myapplication D/Sun:: onCreateDialog
06-17 12:10:18.373 18470-18470/com.sunjing.myapplication D/Sun:: onPrepareDialog


        (2)先点击createDialog按钮,等dialog显示后,再点击dialog的"OK"按钮,取消dialog的显示

06-17 12:10:18.353 18470-18470/com.sunjing.myapplication D/Sun:: showDialog
06-17 12:10:18.353 18470-18470/com.sunjing.myapplication D/Sun:: onCreateDialog
06-17 12:10:18.373 18470-18470/com.sunjing.myapplication D/Sun:: onPrepareDialog
06-17 12:10:31.973 18470-18470/com.sunjing.myapplication D/Sun:: dismissDialog

        (3)先点击createDialog按钮,等dialog显示后,再点击dialog的"OK"按钮,取消dialog的显示,再次点击createDialog按钮

06-17 12:10:18.353 18470-18470/com.sunjing.myapplication D/Sun:: showDialog
06-17 12:10:18.353 18470-18470/com.sunjing.myapplication D/Sun:: onCreateDialog
06-17 12:10:18.373 18470-18470/com.sunjing.myapplication D/Sun:: onPrepareDialog
06-17 12:10:31.973 18470-18470/com.sunjing.myapplication D/Sun:: dismissDialog
06-17 12:10:47.977 18470-18470/com.sunjing.myapplication D/Sun:: showDialog
06-17 12:10:47.977 18470-18470/com.sunjing.myapplication D/Sun:: onPrepareDialog

        (4) 先点击 createDialog按钮,等dialog显示后,再点击dialog的"OK"按钮, 取消dialog的显示,然后再点击removeDialog按钮,最后再点击 createDialog按钮

06-17 12:11:15.241 22224-22224/com.sunjing.myapplication D/Sun:: showDialog
06-17 12:11:15.241 22224-22224/com.sunjing.myapplication D/Sun:: onCreateDialog
06-17 12:11:15.265 22224-22224/com.sunjing.myapplication D/Sun:: onPrepareDialog
06-17 12:11:20.665 22224-22224/com.sunjing.myapplication D/Sun:: dismissDialog
06-17 12:11:21.361 22224-22224/com.sunjing.myapplication D/Sun:: removeDialog
06-17 12:11:21.841 22224-22224/com.sunjing.myapplication D/Sun:: showDialog
06-17 12:11:21.841 22224-22224/com.sunjing.myapplication D/Sun:: onCreateDialog
06-17 12:11:21.845 22224-22224/com.sunjing.myapplication D/Sun:: onPrepareDialog

        onCreateDialog是创建dialog并返回所创建的dialog对象的,dimissDialog执行后,再去showDialog,发现没有继续执行onCreateDialog方法,即没有再去创建对象,可以理解为从某个所存储的对象中拿到了之前所创建的dialog对象。
        然而,在removeDialog之后,发现再去showDialog,需要执行onCreateDialog,也就是说removeDialog删除了之前创建的dialog对象,那么以之前的id去获取dialog就需要重新再创建一个dialog,也就是要重新执行重写的onCreateDialog了。
        以上,是当前的猜测,具体还需要看源码,来理解为什么。

2.源码分析

        下面以Activity的源码进行分析

        showDialog方法:

// 调用showDialog(id, null)方法
public final void showDialog(int id) {
    showDialog(id, null);
}
 
public final boolean showDialog(int id, Bundle args) {
    // private SparseArray<ManagedDialog> mManagedDialogs;
    if (mManagedDialogs == null) {
        mManagedDialogs = new SparseArray<ManagedDialog>();
    }
    // 通过id获取ManagedDialog对象(id还是蛮重要的)
    ManagedDialog md = mManagedDialogs.get(id);
    if (md == null) { // 获取不到就重新创建
        md = new ManagedDialog();
        md.mDialog = createDialog(id, null, args); // 调用createDialog创建dialog(只需创建,无需show)
        if (md.mDialog == null) {
            return false;
        }
        mManagedDialogs.put(id, md); // 将创建好的dialog以及id一起放到集合中,方便后面获取
    }
 
    md.mArgs = args;
    onPrepareDialog(id, md.mDialog, args); // 调用onPrepareDialog方法,在dialog显示之前的其他逻辑控制
    md.mDialog.show(); // 显示dialog
    return true; // 根据返回值可以判断是否创建成功
}


        createDialog方法:

// createDialog方法
private Dialog createDialog(Integer dialogId, Bundle state, Bundle args) {
    // 调用onCreateDialog方法去执行具体的创建dialog的逻辑,即Activity的继承类需要去重写这个方法
    final Dialog dialog = onCreateDialog(dialogId, args);
    if (dialog == null) {
        return null;
    }
    dialog.dispatchOnCreate(state);
    return dialog; // 返回创建的这个dialog对象
}


        onCreateDialog方法:

// Activity自身的onCreateDialog方法返回值为空
protected Dialog onCreateDialog(int id, Bundle args) {
    return onCreateDialog(id);
}
 
protected Dialog onCreateDialog(int id) {
    return null;
}


        onPrepareDialog方法:

// 在dialog显示之前,可以做一些其他相应的逻辑设置工作
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
    onPrepareDialog(id, dialog);
}
 
protected void onPrepareDialog(int id, Dialog dialog) {
    dialog.setOwnerActivity(this);
}


        dismissDialog方法:

// dismissDialog方法
public final void dismissDialog(int id) {
    if (mManagedDialogs == null) {
        throw missingDialog(id);
    }
 
    // 获取id对应的dialog
    final ManagedDialog md = mManagedDialogs.get(id);
    if (md == null) {
        throw missingDialog(id);
    }
    // 不显示dialog,但是该dialog依然还在SparseArray中
    md.mDialog.dismiss();
}


        removeDialog方法:

// removeDialog方法
public final void removeDialog(int id) {
    if (mManagedDialogs != null) {
        final ManagedDialog md = mManagedDialogs.get(id); // 根据id获取dialog对象
        if (md != null) {
            md.mDialog.dismiss(); // dismiss掉dialog
            mManagedDialogs.remove(id); // 并且从SparseArray中移除掉该id相应的对象
        }
    }
}


        ManagedDialog类(Activity的内部类):

// ManagedDialog类
private static class ManagedDialog {
    Dialog mDialog;
    Bundle mArgs;
}
private SparseArray<ManagedDialog> mManagedDialogs;

        根据上面的源码分析发现,在dismissDialog后,dialog仅仅是不显示了,但是dialog对象并没有从SparseArray中删除,所以在showDialog后,是可以通过id从SparseArray直接获取这个dialog的,无需再次重新创建。

        然而removeDialog时,不仅dismiss掉这个dialog,此外,还从SparseArray中直接删除id对应的dialog对象,所以SparseArray不存在这个id的dialog对象了,如果还要显示这个dialog的话,还需要再次重新创建这个dialog,在进行显示。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值