Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用反射访问DialogFragment中的某些字段_Java_Android_Android Fragments_Reflection - Fatal编程技术网

Java 使用反射访问DialogFragment中的某些字段

Java 使用反射访问DialogFragment中的某些字段,java,android,android-fragments,reflection,Java,Android,Android Fragments,Reflection,我有一个类BaseDialog扩展了DialogFragment 过了一会儿,我发现默认的DialogFragment.show()可能会导致一些问题-如果活动正在关闭或被破坏等等 在查看DialogFragment的反编译(?)源代码后,我无意中发现了这段代码: public void show(FragmentManager manager, String tag) { mDismissed = false; mShownByMe = true; FragmentTr

我有一个类
BaseDialog扩展了DialogFragment

过了一会儿,我发现默认的DialogFragment.show()可能会导致一些问题-如果活动正在关闭或被破坏等等

在查看DialogFragment的反编译(?)源代码后,我无意中发现了这段代码:

public void show(FragmentManager manager, String tag) {
    mDismissed = false;
    mShownByMe = true;
    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commit();
}
我想尝试一下我自己的一个小技巧,以消除在活动通过其
onSaveInstanceState()
调用后显示/取消对话框的错误

我想到了这个:

public void showAllowingStateLoss(FragmentManager manager, String tag) {
    try {
        Class thiz = super.getClass();
        Field dismissed = thiz.getField("mDismissed");
        dismissed.setAccessible(true);
        dismissed.set(thiz, false);
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } //mDismissed = false;

    try {
        Class thiz = super.getClass();
        Field shown = thiz.getField("mShownByMe");
        shown.setAccessible(true);
        shown.set(thiz, true);
    } catch(IllegalAccessException e) {
        e.printStackTrace();
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } //mShownByMe = true;

    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commitAllowingStateLoss();
}
这很好用

我现在的问题是,我似乎无法访问DialogFragment的一些字段,将它们设置为与原始源代码相同的正确预期值

W/System.err( 2510): java.lang.NoSuchFieldException: mDismissed
W/System.err( 2510):    at java.lang.Class.getField(Class.java:1048)
W/System.err( 2510):    at com.dpd.navigator.ui.dialogs.BaseDialog.showAllowingStateLoss(BaseDialog.java:70)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin.openConfirmationDialog(ActivityLogin.java:250)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin.access$600(ActivityLogin.java:45)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin$SOAPListener_getUserLogin.onSOAPSuccess(ActivityLogin.java:306)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin$SOAPListener_getUserLogin.onSOAPSuccess(ActivityLogin.java:262)
W/System.err( 2510):    at com.dpd.navigator.backend.soap.SOAPHelper$20.onPostExecute(SOAPHelper.java:1290)
W/System.err( 2510):    at android.os.AsyncTask.finish(AsyncTask.java:632)
W/System.err( 2510):    at android.os.AsyncTask.access$600(AsyncTask.java:177)
W/System.err( 2510):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
W/System.err( 2510):    at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err( 2510):    at android.os.Looper.loop(Looper.java:155)
W/System.err( 2510):    at android.app.ActivityThread.main(ActivityThread.java:5696)
W/System.err( 2510):    at java.lang.reflect.Method.invoke(Native Method)
W/System.err( 2510):    at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err( 2510):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
W/System.err( 2510):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
W/System.err( 2510): java.lang.NoSuchFieldException: mShownByMe
W/System.err( 2510):    at java.lang.Class.getField(Class.java:1048)
W/System.err( 2510):    at com.dpd.navigator.ui.dialogs.BaseDialog.showAllowingStateLoss(BaseDialog.java:81)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin.openConfirmationDialog(ActivityLogin.java:250)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin.access$600(ActivityLogin.java:45)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin$SOAPListener_getUserLogin.onSOAPSuccess(ActivityLogin.java:306)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin$SOAPListener_getUserLogin.onSOAPSuccess(ActivityLogin.java:262)
W/System.err( 2510):    at com.dpd.navigator.backend.soap.SOAPHelper$20.onPostExecute(SOAPHelper.java:1290)
W/System.err( 2510):    at android.os.AsyncTask.finish(AsyncTask.java:632)
W/System.err( 2510):    at android.os.AsyncTask.access$600(AsyncTask.java:177)
W/System.err( 2510):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
W/System.err( 2510):    at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err( 2510):    at android.os.Looper.loop(Looper.java:155)
W/System.err( 2510):    at android.app.ActivityThread.main(ActivityThread.java:5696)
W/System.err( 2510):    at java.lang.reflect.Method.invoke(Native Method)
W/System.err( 2510):    at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err( 2510):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
W/System.err( 2510):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
W/System.err( 2510): java.lang.NoSuchFieldException: mViewDestroyed
W/System.err( 2510):    at java.lang.Class.getField(Class.java:1048)
W/System.err( 2510):    at com.dpd.navigator.ui.dialogs.BaseDialog.showAllowingStateLoss(BaseDialog.java:95)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin.openConfirmationDialog(ActivityLogin.java:250)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin.access$600(ActivityLogin.java:45)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin$SOAPListener_getUserLogin.onSOAPSuccess(ActivityLogin.java:306)
W/System.err( 2510):    at com.dpd.navigator.ui.activities.ActivityLogin$SOAPListener_getUserLogin.onSOAPSuccess(ActivityLogin.java:262)
W/System.err( 2510):    at com.dpd.navigator.backend.soap.SOAPHelper$20.onPostExecute(SOAPHelper.java:1290)
W/System.err( 2510):    at android.os.AsyncTask.finish(AsyncTask.java:632)
W/System.err( 2510):    at android.os.AsyncTask.access$600(AsyncTask.java:177)
W/System.err( 2510):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
W/System.err( 2510):    at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err( 2510):    at android.os.Looper.loop(Looper.java:155)
W/System.err( 2510):    at android.app.ActivityThread.main(ActivityThread.java:5696)
W/System.err( 2510):    at java.lang.reflect.Method.invoke(Native Method)
W/System.err( 2510):    at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err( 2510):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
W/System.err( 2510):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
我想知道为什么我不能访问这些字段。。。。它们不是静态的,因此getField()应该可以工作。我也尝试了
getDeclaredField()
——没有骰子

所以我开始怀疑——用反射来访问这些字段是否可行?我知道有些Android代码(SDK代码)“只是为了展示”,因为我们不能触摸它-它在
AndroidRuntime
过程中运行,这就是反射无法在那里做任何事情的原因

这就是为什么我要问这个问题:我找不到这些字段是因为它们在AndroidRuntime进程中运行还是因为我做错了什么

我可以接受第一个病例。如果是第二种情况,我真的希望将它们设置为预期值

另外,我真的不想鼓吹为什么使用
committeallowingstateloss
是错误和/或不好的。问题的焦点不是这个问题的焦点是为什么我找不到这些字段?

提前感谢您的帮助:)

编辑:
下面的日志说明使用
getDeclaredField
也不起作用

W/System.err(  330): java.lang.NoSuchFieldException: mDismissed
W/System.err(  330):    at java.lang.Class.getDeclaredField(Class.java:886)
W/System.err(  330):    at com.dpd.navigator.ui.dialogs.BaseDialog.showAllowingStateLoss(BaseDialog.java:70)
W/System.err(  330):    at com.dpd.navigator.ui.activities.ActivityMenu.openProfile(ActivityMenu.java:275)
W/System.err(  330):    at com.dpd.navigator.ui.activities.ActivityMenu.access$000(ActivityMenu.java:31)
W/System.err(  330):    at com.dpd.navigator.ui.activities.ActivityMenu$1.onClick(ActivityMenu.java:74)
W/System.err(  330):    at android.view.View.performClick(View.java:4785)
W/System.err(  330):    at android.view.View$PerformClick.run(View.java:19858)
W/System.err(  330):    at android.os.Handler.handleCallback(Handler.java:739)
W/System.err(  330):    at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err(  330):    at android.os.Looper.loop(Looper.java:155)
W/System.err(  330):    at android.app.ActivityThread.main(ActivityThread.java:5696)
W/System.err(  330):    at java.lang.reflect.Method.invoke(Native Method)
W/System.err(  330):    at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err(  330):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
W/System.err(  330):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
编辑2:

由于@pskink和@derek fung的输入,我将代码更改为:

public void showAllowingStateLoss(FragmentManager manager, String tag) {
    try {
//      Class<? extends DialogFragment> thiz = DialogFragment.class;
        Class<? extends DialogFragment> thiz = ((DialogFragment)this).getClass();
        Field dismissed = thiz.getDeclaredField("mDismissed"); <-- line 71
        dismissed.setAccessible(true);
        dismissed.set(this, false);
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } //mDismissed = false;

    try {
        Class<? extends DialogFragment> thiz = ((DialogFragment)this).getClass();
//      Field shown = thiz.getField("mShownByMe");
        Field shown = thiz.getDeclaredField("mShownByMe"); <-- line 83
        shown.setAccessible(true);
        shown.set(this, true);
    } catch(IllegalAccessException e) {
        e.printStackTrace();
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } //mShownByMe = true;

    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commitAllowingStateLoss();
}
成功的关键在于:

public void showAllowingStateLoss(FragmentManager manager, String tag) {
    try {
        Class<? extends DialogFragment> thiz = DialogFragment.class;
        Field dismissed = thiz.getDeclaredField("mDismissed");
        dismissed.setAccessible(true);
        dismissed.set(this, false);
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } //mDismissed = false;

    try {
        Class<? extends DialogFragment> thiz = DialogFragment.class;
        Field shown = thiz.getDeclaredField("mShownByMe");
        shown.setAccessible(true);
        shown.set(this, true);
    } catch(IllegalAccessException e) {
        e.printStackTrace();
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } //mShownByMe = true;

    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commitAllowingStateLoss();
}
public void showAllowingStateLoss(碎片管理器,字符串标记){
试一试{

类您应该将
super.getClass()
替换为
DialogFragment.Class

getDeclaredField()一起使用

这是因为
super.getClass()
将返回实例的类,而不是您想要的超类。并且
getField()
无法获取
private
字段

编辑:


discomered.set(thiz,false);
应该替换为
discomered.set(this,false);
因为设置字段需要提供对象而不是类。

getDeclaredField
它可以工作,顺便说一句,你真的是在自找麻烦……@pskink正如我说的,
getField()
getDeclaredField()
找不到它。我将用logcat更新帖子,以表明我也尝试过。最终的编辑版本解决了这个问题
DialogFragment.getClass()
无法使用,因为“无法从静态上下文访问非静态方法”.Using
DialogFragment.class
抛出
java.lang.IllegalArgumentException:预期接收类型为android.app.DialogFragment,但得到了java.lang.class
但我会尝试类似的方法,答案仍然很有用:)您应该使用
disposed.set(this,false);
而不是
disposed.set(thiz,false);
,您需要提供对象,而不是classno dice,相同的结果。我将用最新的结果和代码更新帖子。您应该使用DialogFragment.ClassAllegalArgumentException是由于您在
集合中使用了
thiz
引起的
public void showAllowingStateLoss(FragmentManager manager, String tag) {
    try {
        Class<? extends DialogFragment> thiz = DialogFragment.class;
        Field dismissed = thiz.getDeclaredField("mDismissed");
        dismissed.setAccessible(true);
        dismissed.set(this, false);
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } //mDismissed = false;

    try {
        Class<? extends DialogFragment> thiz = DialogFragment.class;
        Field shown = thiz.getDeclaredField("mShownByMe");
        shown.setAccessible(true);
        shown.set(this, true);
    } catch(IllegalAccessException e) {
        e.printStackTrace();
    } catch(NoSuchFieldException e) {
        e.printStackTrace();
    } //mShownByMe = true;

    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commitAllowingStateLoss();
}