Я работаю над приложением для 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;
}
}
Я надеюсь, что кто-то может мне помочь :)




Вы не можете напрямую получить доступ к методам 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 ().