Android: how to get an instance of a member field

2019-06-13 01:44发布

Here's a fairly convoluted question. I am trying to access the webviewcore instance member of a webview via reflection. I want a reference to the webviewcore that is used by my webview, so that i can invoke a method that the webviewcore uses. I have to do this via reflection because the public sdk does not let you access this class. I know using reflection to do this is discouraged but i've made my peace with that.

I've read here that to achieve this i would do something like this:

Class  aClass = MyObject.class
Field field = aClass.getField("someField");

MyObject objectInstance = new MyObject();

Object value = field.get(objectInstance);

field.set(objetInstance, value);

The problem with doing this (and maybe im misunderstanding this) is that it looks like i have to create a new instance of the WebViewCore to work with and then set it back to my instance. First and formost, am i understanding this correctly. If so, then can someone translate the code above to do what i am looking for it to do. If my understanding is incorrect, does anyone know how else i can access the WebViewCore of an instance of a webview?

Thanks!

EDIT: Due to confusion i will restate my question. I have an instance of a webview. That webview has a member field called 'mWebViewCore' which is an instance of the WebViewCore class. The WebViewCore has a member class called called TextSelectionData. I need to access the the TextSelectionData object via reflection. I know how to access fields and methods of the webview through reflection. So i can get mWebViewCore field, but i don't know how to take that field and access it's fields, methods, classes etc. The broadstrokes are take an instance of an object, find a specific field in that instance, and access the fields of that field.

Sorry for the confusion. It come from my weak understanding of reflection, and partially from the fact that i didn't adequately understand WebViewCore class. here's where i've gotten to in the code:

Class c = mWebView.getClass();

       try {
            Field webViewCoreField = c.getDeclaredField("mWebViewCore");
            webViewCoreField.setAccessible(true);
            //how do i get the fields of webViewCoreField?
        }   

2条回答
啃猪蹄的小仙女
2楼-- · 2019-06-13 02:10

Assuming a WebViewCore with a private String s field:

public class WebViewCore {
    private String s;
    public WebViewCore(String s) { this.s = s; }
    @Override
    public String toString() {
        return "WebViewCore{" + "s='" + s + '\'' + '}';
    }
}

Assuming a WebView with a private WebViewCore webViewCore field:

public class WebView {
    private WebViewCore webViewCore;
    public WebView() { webViewCore = new WebViewCore("ohai"); }
}

Now we reflect:

public class Main {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        // First get the private WebViewCore field...
        Field fWvc = WebView.class.getDeclaredField("webViewCore");
        fWvc.setAccessible(true);
        System.out.println(fWvc);

        // Then get an instance of a WebView; you already have one,
        // I'm constructing one...
        WebView wv = new WebView();
        WebViewCore wvc = (WebViewCore) fWvc.get(wv);
        System.out.println(wvc);

        // Now get the private String field from the WebViewCore class...
        Field fS = WebViewCore.class.getDeclaredField("s");
        fS.setAccessible(true);
        System.out.println(fS);

        // Now get the value of the private String field from the instance
        // of the WebViewCore we retrieved above...
        String s = (String) fS.get(wvc);
        System.out.println(s);
    }

}

So, here's my rant: reflection is a relatively advanced technique, although it's pretty straight-forward. (With the caveat I've been doing this for a really long time, with languages that have better reflective abilities than Java.)

This seems to still be a bit out-of-reach--that being the case, I'd be really, really careful about using it, and would avoid it at essentially any cost. I question your need to do whatever it is you're trying to do, and after that, I'd question the wisdom of doing whatever it is you're trying to, until stuff like the toy example we're mucking with here causes zero conceptual issues.

Here there be dragons, and they will cook and eat you.

查看更多
Emotional °昔
3楼-- · 2019-06-13 02:27

Reflection offers you ability to access private fields, private methods of a class(or rather, an object), and runtime informations.

Your understanding of reflection is correct. But in the code snippet you posted, your use of reflection does not make sense to me. You are setting a value to a field with a value from that field, i.e. you are doing something like:

obj.setValue(obj.getValue());

You said you wanted to access a private field of WebView, I assume you already have the WebView instance, so once you get the Field reference, you just set the value of that field on your original WebView instance, you don't and shouldn't create a new WebView object, because it was the original WebView object that you wanted to operate on.

Something like this:

WebView myWebView = ...;
Object myValueToSet = ...; 
Class webViewClass = WebView.class
Field field = webViewClass.getField("someField");
field.setAccessible(true);
field.set(myWebView, myValueToSet);
查看更多
登录 后发表回答