栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android重置APN时提示弹窗不消失问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android重置APN时提示弹窗不消失问题

问题:
  • APN列表界面执行重置(“Reset to default” 菜单)时,偶现restore消息提示弹窗不消失。
  • 切换APN或编辑当前选中APN内容保存后,迅速重置APN会高概率复现问题。
相关流程

入口:ApnSettings.java (revision 2a149d99) - OpenGrok cross reference for /packages/apps/Settings/src/com/android/settings/network/apn/ApnSettings.java

1. 菜单选项重置APN

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case MENU_NEW:
            addNewApn();
            return true;
        case MENU_RESTORE:
            restoreDefaultApn();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

2. 执行重置APN流程,后续工作交由Handler

private boolean restoreDefaultApn() {
    //1.UI显示提示对话框
    showDialog(DIALOG_RESTORE_DEFAULTAPN);
    //2.设置标志位
    mRestoreDefaultApnMode = true;
    //3.创建UI和逻辑处理程序:RestoreApnUiHandler和RestoreApnProcessHandler
    if (mRestoreApnUiHandler == null) {
        mRestoreApnUiHandler = new RestoreApnUiHandler();
    }
    //(HandlerThread)mRestoreDefaultApnThread 定义时没有初始化,在这里进行。
    if (mRestoreApnProcessHandler == null || mRestoreDefaultApnThread == null) {
        mRestoreDefaultApnThread = new HandlerThread(
                "Restore default APN Handler: Process Thread");
        mRestoreDefaultApnThread.start();
        mRestoreApnProcessHandler = new RestoreApnProcessHandler(
                mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
    }

    mRestoreApnProcessHandler
            .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
    return true;
}

3.业务线程RestoreApnProcessHandler处理消息EVENT_RESTORE_DEFAULTAPN_START

private class RestoreApnProcessHandler extends Handler {
    private Handler mRestoreApnUiHandler;

    RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
        super(looper);
        this.mRestoreApnUiHandler = restoreApnUiHandler;
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            //1.收到处理restoreDefaultApn方法中mRestoreApnProcessHandler发出的信息
            case EVENT_RESTORE_DEFAULTAPN_START:
                //2.重置业务的数据库内容处理
                final ContentResolver resolver = getContentResolver();
                resolver.delete(getUriForCurrSubId(DEFAULTAPN_URI), null, null);
                //3.UI线程发出重置完成的消息
                mRestoreApnUiHandler
                    .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_COMPLETE);
                break;
        }
    }
}

 4. UI线程RestoreApnUiHandler处理消息EVENT_RESTORE_DEFAULTAPN_COMPLETE

private class RestoreApnUiHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
                final Activity activity = getActivity();
                if (activity == null) {
                    mRestoreDefaultApnMode = false;
                    return;
                }
                fillList();
                getPreferenceScreen().setEnabled(true);
                mRestoreDefaultApnMode = false;
                //移除对话框并显示Toast提示
                removeDialog(DIALOG_RESTORE_DEFAULTAPN);
                Toast.makeText(
                    activity,
                    getResources().getString(
                            R.string.restore_default_apn_completed),
                    Toast.LENGTH_LONG).show();
                break;
        }
    }
}

可能原因

1. 由于对Phone状态监听中有显示Dialog的调用,但是没有remove该对话框的回调条件。

ApnSettings.java (revision 2a149d99) - OpenGrok cross reference for /packages/apps/Settings/src/com/android/settings/network/apn/ApnSettings.java

private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
    @Override
    public void onPreciseDataConnectionStateChanged(
            PreciseDataConnectionState dataConnectionState) {
        if (dataConnectionState.getState() == TelephonyManager.DATA_CONNECTED) {
            if (!mRestoreDefaultApnMode) {
                fillList();
            } else {
                showDialog(DIALOG_RESTORE_DEFAULTAPN);
            }
        }
    }
};

2.Settings Dialog的机制

SettingsPreferenceFragment.java (revision 2a149d99) - OpenGrok cross reference for /packages/apps/Settings/src/com/android/settings/SettingsPreferenceFragment.java

// Dialog management

protected void showDialog(int dialogId) {
    if (mDialogFragment != null) {
        Log.e(TAG, "Old dialog fragment not null!");
    }
    mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId);
    mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId));
}

@Override
public Dialog onCreateDialog(int dialogId) {
    return null;
}

@Override
public int getDialogMetricsCategory(int dialogId) {
    return 0;
}

protected void removeDialog(int dialogId) {
    // mDialogFragment may not be visible yet in parent fragment's onResume().
    // To be able to dismiss dialog at that time, don't check
    // mDialogFragment.isVisible().
    if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
        mDialogFragment.dismissAllowingStateLoss();
    }
    mDialogFragment = null;
}


protected void setOnCancelListener(DialogInterface.OnCancelListener listener) {
    if (mDialogFragment != null) {
        mDialogFragment.mOnCancelListener = listener;
    }
}


protected void setOnDismissListener(DialogInterface.OnDismissListener listener) {
    if (mDialogFragment != null) {
        mDialogFragment.mOnDismissListener = listener;
    }
}

public void onDialogShowing() {
    // override in subclass to attach a dismiss listener, for instance
}

总结
  • 关注showDialog(DIALOG_RESTORE_DEFAULTAPN)和removeDialog(DIALOG_RESTORE_DEFAULTAPN)的回调。
  • 由于时序问题可能导致对话框多次被创建但有些情况没有对应的移除操作。
    • 通过单例模式解决?
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1005778.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号