Вызов нестатического метода из другого класса в Java

Я работаю над приложением для Android, но застрял над проблемой, на которую не могу найти ответа. Я хочу вызвать метод updateTime в классе MainActivity из метода run (таким образом вызывая его из потока) в классе TaskHandler.

Я искал ответ в Google около часа, посетил несколько веб-сайтов и нашел несколько решений, из которых у меня не сработало. Я также спрашивал об этом на серверах разногласий LinusTechTips и Corsair.

Класс 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:

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;
        }
    }

Я надеюсь, что кто-то может мне помочь :)

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
71
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы не можете напрямую получить доступ к методам Activity вне самого Activity. Рекомендуемый способ связи между компонентами - использовать Трансляции.

У вас есть прямой доступ к вашему Activity, потому что вы создаете экземпляр TaskHandler из него. Вы можете просто передать свою Activity в конструктор TaskHandler (и сохранить ее как глобальную переменную в TaskHandler), но это может привести к сбою, если эта Activity будет завершена до выполнения TaskHandler.

Добавьте контекст в конструктор TaskHandler:

private Context context;

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

и создайте экземпляр TaskHandler с помощью

new TaskHandler(getApplicationContext());

и вы сможете отправить Broadcast, который затем можно будет получить в BroadcastReceiver, зарегистрированном внутри вашей Activity (прочтите ссылку для получения подробной информации о BroadcastReceivers и т. д.).

Замените Context на MainActivity, а getApplicationContext() на this, и вы можете просто вызвать нужный метод напрямую, но это может вызвать сбои, и это будет работать, только если TaskHandler используется только внутри MainActivity.

Если он используется только внутри MainActivity, просто сделайте его внутренним классом, а затем вы можете вызвать метод напрямую, без какой-либо ссылки.

Независимо от того, что вы делаете, вы не можете самостоятельно создать новый экземпляр классов Activity и ожидать, что они будут работать.

Используйте трансляции. В вашем классе TaskHandler изнутри метода "run" отправьте широковещательную рассылку:

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

В вашем классе 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"));
Ответ принят как подходящий

Сделайте TaskHandler внутренним классом внутри MainActivity. Затем вы сможете вызвать updateTime (). И отбросьте эту статическую конечную переменную MainActivity, она вам не понадобится, если TaskHandler находится внутри MainActivity. Никогда не создавайте действия с новым оператором.

Еще одна вещь, с которой вы, вероятно, столкнетесь, - вы не можете обновить пользовательский интерфейс из фонового потока, поэтому вы, вероятно, захотите использовать runOnUiThread (Runnable) либо при вызове updateTime (), либо внутри updateTime ().

Другие вопросы по теме