在Thread内部调用方法

时间:2016-10-03 15:12:13

标签: java android multithreading reflection

我刚刚从这个link了解了调用方法,现在我正在尝试使用它,但我无法使用我想要的逻辑。 我只是想从一个Thread调用一个方法。

我已经使用了以下代码并且它有效。但这里的问题是循环, 循环必须列出类中的所有方法,并检查特定方法是否存在然后调用它。

Class myclass = Class.forName("com.package.MainActivity");
Method[] methods = myclass.getMethods();
for (int i = 0; i < methods.length; i++) {
    if (methods[i].getName().equals("methodName")) {
        Log.w(TAG, "Method Found!");
        methods[i].invoke("methodName", "string data", 0123, 123, "string data");
    }
}

我想用下面的代码简化它,但它一直告诉我找不到该方法。 ERROR: java.lang.NoSuchMethodException: methodName []

Class c=Class.forName("com.package.MainActivity");
Method m=c.getMethod("methodName");
Object t = c.newInstance();
Object o= m.invoke(t,"string data", 0123, 123, "string data");

我也尝试过以下代码,但它也无效,错误说明:Can't create handler inside thread that has not called Looper.prepare()

Object carObj = Class.forName("com.package.MainActivity").newInstance();
Method method = carObj.getClass().getMethod("methodName");
method.invoke(method, "string data", 0123, 123, "string data");

我正在使用以下代码执行上述所有代码:

应该调用该方法的主类

public class MainActivity extends AppCompatActivity {

    static MyHelper myHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnStart = (Button)findViewById(R.id.btnStart);

        myHelper = new MyHelper(this);
        myHelper.StartThread();

    }

    /*The Method to Invoke*/
    public static void methodName(String data1, int var1, int var2, String data2){
        //some code here...
    }
}

用于启动线程的助手类,包括我的一些功能

public class MyHelper{
    private Context context;
    public MyHelper(Context context){
       this.context = context;
    }

    public static void StartThread(){
        TheThread theThread = new TheThread(context);
        Thread t = new Thread(theThread);
        t.start();
    }

    //Some code below
}

应该调用方法的线程

public class TheThread implements Runnable{

    private Context context;

    public TheThread(Context context){
       this.context = context;
    }

    @Override
    public void run(){
        try{

            String className = context.getClass().getName(); //The Class Name including its package.

            //First Attempt
            /*Class myclass = Class.forName(className);
            Method[] methods = myclass.getMethods();
            for (int i = 0; i < methods.length; i++) {
                if (methods[i].getName().equals("methodName")) {
                    Log.w(TAG, "Method Found!");
                    methods[i].invoke("methodName", "string data", 0123, 123, "string data");
                }
            } */

            //Second Attempt
            /*Class c=Class.forName(className);
            Method m=c.getMethod("methodName");
            Object t = c.newInstance();
            Object o= m.invoke(t,"string data", 0123, 123, "string data");*/

            //Third attempt
            /*Object carObj = Class.forName(className).newInstance();
            Method method = carObj.getClass().getMethod("methodName");
            method.invoke(method, "string data", 0123, 123, "string data"); */

        }catch(Exception e){
            Log.e("Invoke Error","Unable to invoke method => " + e.toString());
        }
    }
}

我现在很喜欢调用方法。我怎么解决这个问题?我不喜欢第一次尝试,因为它需要列出类中的所有方法,以便在调用之前检查特定方法。

1 个答案:

答案 0 :(得分:0)

你的第二个例子几乎没问题,除了你必须告诉它该方法有哪些参数。

Class c=Class.forName("com.package.MainActivity");
Method m=c.getMethod("methodName", String.class, int.class, int.class, String.class);
Object t = c.newInstance();
Object o= m.invoke(t,"string data", 0123, 123, "string data");

请记住,方法签名始终由以下内容组成:methodName +参数类型列表。如果你不告诉参数类型,它将寻找一个没有任何参数的方法。这就是为什么它会在你的第二个例子中抛出NoSuchMethod异常。

作为旁注,如果您的方法是静态的(如示例中的情况那样),请不要打扰类实例。您可以传递null作为m.invoke调用的第一个参数。请参阅方法javadoc:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-