简体   繁体   English

从Java中的其他类调用非静态方法

[英]Call a non static method from a different class in Java

I'm working on an Android app, but am stuck at a problem I can't seem to find an answer to. 我正在开发一个Android应用程序,但是遇到了一个我似乎找不到答案的问题。 I want to call the method "updateTime" in class "MainActivity" from method "run" (thus calling it from a Thread) in class "TaskHandler". 我想从类“ TaskHandler”中的方法“运行”(因此从线程调用它)中调用类“ MainActivity”中的方法“ updateTime”。

I've Googled for the answer for about an hour now, visited multiple websites and found multiple solutions, of which non worked for me. 我已经用Google搜索了大约一个小时的答案,访问了多个网站并找到了多个解决方案,但这些解决方案都不适合我。 I have also asked about it in the LinusTechTips and Corsair discord servers. 我还曾在LinusTechTips和Corsair不和谐服务器中询问过此问题。

MainActivity class: MainActivity类:

    package thedutchmc.net.alarm;

import android.os.Bundle;
import android.widget.EditText;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.time.LocalTime;


public class MainActivity extends AppCompatActivity {

    public static String alarmTime;
    public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
    public static boolean alarmBool = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView mTextView = (TextView) findViewById(R.id.currentTime);

        mTextView.setText("Current Time: ");
        Main.scheduler.scheduleAtFixedRate(new TaskHandler(), 1, 1, TimeUnit.SECONDS);
    }

    public void onSubmit(View v){
        System.out.println("Submit!");
        EditText alarmTimeEditText = (EditText) findViewById(R.id.setAlarmTime);
        alarmTime = alarmTimeEditText.getText().toString();
        System.out.println("MainActivity (alarmTime): " + alarmTime);
        alarmBool = true;

    }

    public void updateTime() {
        TextView seeTime = (TextView) findViewById(R.id.currentTime);
        seeTime.setText(LocalTime.now().toString());
    }
}

TaskHandler class: TaskHandler类别:

package thedutchmc.net.alarm;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class TaskHandler implements Runnable {

    final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
    public static boolean isRinging = false;
    private String alarmTime;
    public static final MainActivity activity = new MainActivity();

    @Override
    public void run() {
        activity.updateTime();
        if (checkAlarmBool()) {
            System.out.println("Bool true! Alarm!");
            Main.alarm.set(false);
            Main.alarm.ringAlarm();
        }
    }

    boolean checkAlarmBool() {
        if (MainActivity.alarmBool && !isRinging) {
            String lTime = LocalTime.now().format(dtf);

            System.out.println("TaskHandler alarmTime: " + MainActivity.alarmTime);
            System.out.println("TaskHandler LocalTime: " + lTime);

            if(lTime.equalsIgnoreCase(MainActivity.alarmTime)) {
                isRinging = true;
                return true;
            } else {

                return false;
            }
        } else {
            return false;
        }
    }

I hope someone can help me :) 我希望有一个人可以帮助我 :)

You can't directly access an Activity's methods outside of the Activity itself. 您不能直接在活动本身之外访问活动的方法。 The recommended way to communicate among components is to use Broadcasts . 在组件之间进行通信的推荐方法是使用Broadcasts

You do have direct access to your Activity, because you instantiate the TaskHandler from it. 您确实可以直接访问Activity,因为您是从Activity实例化TaskHandler的。 You could just pass your Activity in the constructor of TaskHandler (and save it as a global variable in the TaskHandler), but this might lead to crashes if that Activity is finished before TaskHandler executes. 您可以只在TaskHandler的构造函数中传递Activity(并将其保存为TaskHandler中的全局变量),但是如果该Activity在TaskHandler执行之前完成,则可能导致崩溃。

Add a Context to TaskHandler's constructor: 将上下文添加到TaskHandler的构造函数中:

private Context context;

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

and instantiate the TaskHandler with 并实例化TaskHandler

new TaskHandler(getApplicationContext());

and you'll be able to send a Broadcast that you can then receive in a BroadcastReceiver registered inside your Activity (read the link for details on BroadcastReceivers and such). 并且您将能够发送广播,然后可以在您的Activity中注册的BroadcastReceiver中接收广播(请阅读链接以获取有关BroadcastReceivers等的详细信息)。

Replace Context with MainActivity , and getApplicationContext() with this , and you can just directly call the method you want, but that can cause crashes, and this will only work if TaskHandler is only used inside MainActivity. MainActivity替换Context ,并使用this替换getApplicationContext() ,您可以直接调用所需的方法,但这会导致崩溃,并且仅当TaskHandler仅在MainActivity内使用时才有效。

If it is only used inside MainActivity, just make it an inner class, and then you can call the method directly, without any reference. 如果仅在MainActivity内部使用它,则使其成为内部类,然后可以直接调用该方法,而无需任何引用。

No matter what you do, you can't make a new instance of Activity classes yourself and expect them to work. 无论您做什么,都无法自己创建Activity类的新实例并期望它们能正常工作。

Use Broadcasts. 使用广播。 In Your TaskHandler class, from inside "run" method, send broadcast: 在您的TaskHandler类中,从“运行”方法内部发送广播:

Intent i = new Intent("run_method");
sendBroadcast(i);

In Your MainActivity class, in onResume(), register Broadcast Receiver: 在您的MainActivity类的onResume()中,注册Broadcast Receiver:

private BroadcastReceiver receiver;
if (receiver == null){
   receiver = new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {
            updateTime();
       }
   };
}
registerReceiver(receiver, new IntentFilter("run_method"));

Make TaskHandler an inner class inside MainActivity. 使TaskHandler成为MainActivity内部的内部类。 Then you'll be able to call updateTime(). 然后,您将能够调用updateTime()。 And drop that static final MainActivity variable, you won't need it if TaskHandler is inside MainActivity. 并删除该静态最终MainActivity变量,如果TaskHandler在MainActivity内部,则将不需要它。 Never create activities with the new operator. 切勿使用新操作员创建活动。

One other thing you'll probably run into, you can't update UI from a background thread, so you'll probably want to use runOnUiThread(Runnable) either when calling updateTime() or inside updateTime(). 您可能会遇到的另一件事是,您无法从后台线程更新UI,因此您可能希望在调用updateTime()或在updateTime()内部使用runOnUiThread(Runnable)。

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

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