简体   繁体   English

由于没有找到构造函数,从类对象动态实例化AsyncTask失败

[英]Dynamically instantiating AsyncTask from class object fails due to no constructor found

I have a few things that need to be done asynchronously during my application's startup process. 在应用程序的启动过程中,我需要异步完成一些操作。 I've created an abstract class that derives from AsyncTask which implements things common to these loading tasks: 我创建了一个抽象类,该抽象类从AsyncTask派生,该类实现了这些加载任务的共同点:

protected abstract class LoadTask extends AsyncTask<Object, Void, Object>{
    MainActivity activity;
    void detach(){
        activity = null;
    }
    void attach(MainActivity a){
        activity = a;
    }

    public LoadTask(MainActivity a){
        super();
        attach(a);
    }

    public abstract boolean shouldRun();

    @Override
    protected void onPostExecute(Object result){
        activity.onFinishLoad(this.getClass(), result);
    }
}

Following is one particular implementation of a concrete subclass: 以下是具体子类的一个特定实现:

public class ItemInfoLoadTask extends LoadTask{

    public ItemInfoLoadTask(MainActivity a){
        super(a);
    }

    public boolean shouldRun(){
        return should_reload("items", item_info_path);
    }

    @Override
    protected Object doInBackground(Object ... params) {
        setProgressMessage("Reading item info...");
        JSONObject result = loadItemInfo();
        return result;
    }

    private JSONObject loadItemInfo(){
        return Util.parseJSONObject(item_info_path);
    }
}

And here is the code that calls these from within the onCreate() method of my activity: 这是从我的活动的onCreate()方法中调用这些代码的代码:

Log.v(TAG, c.getName());
Class[] types = {MainActivity.class};
Constructor construct = c.getConstructor(types);
task = (LoadTask)(construct.newInstance(this));

And here is the log: 这是日志:

12-17 10:26:25.750: V/MainActivity(25188): com.mycompany.mypackage.MainActivity$ItemInfoLoadTask
12-17 10:26:25.760: E/MainActivity(25188): this shouldn't happen
12-17 10:26:25.760: E/MainActivity(25188): java.lang.NoSuchMethodException: <init> [class com.mycompany.mypackage.MainActivity]
12-17 10:26:25.760: E/MainActivity(25188):        at java.lang.ClassMembers.getConstructorOrMethod(ClassMembers.java:235)
12-17 10:26:25.760: E/MainActivity(25188):        at java.lang.Class.getConstructor(Class.java:459)
12-17 10:26:25.760: E/MainActivity(25188):        at com.mycompany.mypackage.MainActivity.onCreate(MainActivity.java:80)
12-17 10:26:25.760: E/MainActivity(25188):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
12-17 10:26:25.760: E/MainActivity(25188):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1715)
12-17 10:26:25.760: E/MainActivity(25188):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1767)
12-17 10:26:25.760: E/MainActivity(25188):        at android.app.ActivityThread.access$1500(ActivityThread.java:122)
12-17 10:26:25.760: E/MainActivity(25188):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1005)
12-17 10:26:25.760: E/MainActivity(25188):        at android.os.Handler.dispatchMessage(Handler.java:99)
12-17 10:26:25.760: E/MainActivity(25188):        at android.os.Looper.loop(Looper.java:132)
12-17 10:26:25.760: E/MainActivity(25188):        at android.app.ActivityThread.main(ActivityThread.java:4028)
12-17 10:26:25.760: E/MainActivity(25188):        at java.lang.reflect.Method.invokeNative(Native Method)
12-17 10:26:25.760: E/MainActivity(25188):        at java.lang.reflect.Method.invoke(Method.java:491)
12-17 10:26:25.760: E/MainActivity(25188):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
12-17 10:26:25.760: E/MainActivity(25188):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
12-17 10:26:25.760: E/MainActivity(25188):        at dalvik.system.NativeStart.main(Native Method)

I can't figure out what I'm doing wrong. 我无法弄清楚我做错了什么。 If it matters any(although I can't see why it should), LoadTask and ItemInfoLoadTask are inner classes in MainActivity 如果它重要(虽然我不明白为什么它应该),LoadTask和ItemInfoLoadTask是MainActivity中的内部类

Non-static inner classes contain implicit reference to the instance of the enclosing class. 非静态内部类包含对封闭类的实例的隐式引用。 All constructors of such inner classes take reference to the instance of enclosing class as an argument. 这些内部类的所有构造函数都引用封闭类的实例作为参数。

A simple example: 一个简单的例子:

import java.lang.reflect.*;

class Foo {
    class Bar {
        public Bar(int a) {
        }
    }

    public static void main(String[] args) {
        for(Constructor c: Bar.class.getDeclaredConstructors()) {
            System.out.println(c);
        }   
    }
}

prints public Foo$Bar(Foo,int) - note the first Foo parameter. print public Foo$Bar(Foo,int) - 注意第一个Foo参数。 The javap tool can show information about structure - declared fields, methods and constructors of Foo$Bar.class : javap工具可以显示有关结构的信息 - 声明Foo$Bar.class字段,方法和构造Foo$Bar.class

Compiled from "Foo.java"
class Foo$Bar extends java.lang.Object{
    final Foo this$0;
    public Foo$Bar(Foo, int);
}

Here you can see this implicit reference to the parent. 在这里,您可以看到对父级的隐式引用。 JVM doesn't know about inner classes so the compiler has to introduce synthetic methods and fields to achieve required behavior. JVM不了解内部类,因此编译器必须引入合成方法和字段来实现所需的行为。 It is usually remain unnoticed until you need something like reflection. 在需要反射之类的东西之前,它通常不会被注意到。

In your particular case you can either make your inner classes static so there will be no implicit reference or remove explicit reference to the MainActivity . 在您的特殊情况下,您可以将内部类设为静态,以便不存在隐式引用,也可以删除对MainActivity显式引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM