[英]How to call a method defined in an Activity class from a (non-activity) Java class
在我的DataTrak活动中,我定义了以下方法:
public void updateTotal(IAmount totalAmount, int transactionType) {
switch (transactionType) {
case AccountTotals.VALUE_CANCELS:
txtView_cancels_value.setText("" + (Long.parseLong(txtView_cancels_value.getText().toString()) + totalAmount.getValue()));
break;
case AccountTotals.VALUE_PAYS:
txtView_pays_value.setText("" + (Long.parseLong(txtView_pays_value.getText().toString()) + totalAmount.getValue()));
break;
case AccountTotals.VALUE_SALES:
txtView_sales_value.setText("" + (Long.parseLong(txtView_sales_value.getText().toString()) + totalAmount.getValue()));
break;
default:
break;
}
btn_total.setBackgroundResource(R.drawable.button_green );
}
该方法计算并更新一些TextView,并更改按钮的颜色。 然后,我需要从Java抽象类调用此方法。 该方法调用出现在非UI线程上运行的方法中。 这是我调用方法的方式:
new Thread()
{
public void run()
{
new DataTrak().runOnUiThread(new Runnable()
{
public void run()
{
new DataTrak().updateTotal(totalAmount,transactionType);
}
});
}
}.start();
问题是我遇到了运行时异常。 这是LogCat的输出:
05-13 16:52:13.325: E/AndroidRuntime(22101): FATAL EXCEPTION: Thread-1577
05-13 16:52:13.325: E/AndroidRuntime(22101): Process: com.ilts.lct, PID: 22101
05-13 16:52:13.325: E/AndroidRuntime(22101): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-13 16:52:13.325: E/AndroidRuntime(22101): at android.os.Handler.<init> (Handler.java:200)
05-13 16:52:13.325: E/AndroidRuntime(22101): at android.os.Handler.<init>(Handler.java:114)
05-13 16:52:13.325: E/AndroidRuntime(22101): at android.app.Activity.<init>(Activity.java:786)
05-13 16:52:13.325: E/AndroidRuntime(22101): at com.ilts.lct.ap.mainframe.DataTrak.<init>(DataTrak.java:37)
05-13 16:52:13.325: E/AndroidRuntime(22101): at com.ilts.lct.ap.customerfunctions.CustomerTransaction$2.run(CustomerTransaction.java:736)
实际上,起初我只有方法调用这一行,但是却遇到了相同的运行时异常。 我搜索“无法在尚未调用Looper.prepare()的线程内创建处理程序”,并且发现了有关此问题的几篇文章。 其中之一使我将方法调用放入新的Thread中,如上所示。 但是我仍然遇到相同的运行时异常。 我应该改变什么? 您能帮助我了解实际的问题以及如何解决吗? 提前致谢。
在阅读@Metero的答案后,下面是Java抽象类中的代码:
public abstract class CustomerTransaction extends Transaction {
...................................................
public interface CallBack {
public void updateTotal(IAmount a,int n);
}
private static CallBack callback;
public static void registerCallback(CallBack callback1){
callback = callback1;
}
/**
* Method to update the transaction state
*
* @param state The new transaction state
**/
public void setState(final int state) {
this.state = state;
/*
* Update the status
*/
if (state == TRANSACTION_COMPLETE) {
new Thread()
{
public void run() {
Looper.prepare();
new DataTrak().runOnUiThread(new Runnable()
{
public void run() {
Log.i("HERE", "HERE");
Looper.prepare();
callback.updateTotal(totalAmount,transactionType);
Looper.loop();
}
});
}
}.start();
}
}
....................
}
您永远不要自己实例化一个Activity,如果您这样做的话,那将不是正常的活动,而只是一个有问题的计划Java对象。
因此,可能要解决的问题是使用观察者模式 ,在该模式中可以使用“回调”方法定义一个接口,然后让Activity实现它并使它订阅通知的“提供者”。 因此,基本上,当此更新线程运行时,您将通过订阅的侦听器列表运行并调度该调用,就像正常的方法调用一样。
只需记住:尊重活动生命周期的'subscribe'和'unsubscribe'.. like在onCreate()上订阅,在onDestroy()上取消订阅。
活动:
public class YourActivity extends Activity implements ControlListener {
public void onCreate(...) {
....
control.registerListener(this);
control.performOperation();
}
public void onDestroy(...) {
....
control.unregisterListener(this);
}
public void updateTotal(String newValue) {
runOnUiThread(new Runnable() {
public void run() {
textView.setText(newValue);
}
});
}
}
控制类别:
public class Control {
private Set<ControlListener> listeners = new HashSet<ControlListener>();
public synchronized void registerListener(ControlListener listener) {
listeners.add(listener);
}
public synchronized void unRegisterListener(ControlListener listener) {
listeners.remove(listener);
}
public synchronized void notifyListeners(String newValue) {
for(ControlListener listener : listeners) {
listener.updateTotal(newValue);
}
}
public void performOperation() {
new Thread() {
public void run() {
String newValue= service.performBackgroundOperationToGetNewValue();
notifyListeners(newValue);
}
}.start();
}
}
控制监听器:
public interface ControlListener {
public void updateTotal(String newValue);
}
另外,您可以使用非常方便的HANDY库在项目上应用Observer模式,即Otto : http : //square.github.io/otto/使用Otto,您不需要注册/注销/在您控件中的notifylisteners方法中,它会自动放置在其他位置。
这个问题的本质暗示存在违反MVC的行为。 而不是在Activity中调用模型的方法,它应该在Activity已在模型上注册的某些回调中调用方法。 此回调应在UI线程中排队。
这不是最佳选择。
new Thread()
{
public void run()
{
new DataTrak().runOnUiThread(new Runnable()
{
public void run()
{
Looper.prepare();//This is not the best choice.
new DataTrak().updateTotal(totalAmount,transactionType);
}
});
}
}.start();
我建议像这样使用AsyncTask。
class SampleTask extends AsyncTask<Boolean, Boolean, Boolean> {
private int totalAmount;
private yourActivity activity;
//passing parameters
public void SampleTask(yourActivity activity){
this.activity = activity;
}
@Override
protected Boolean doInBackground(Boolean... params) {
while (totalAmount < 10){
totalAmount++;
}
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// this is not the best choice
// because you are creating two instances.
new DataTrak().updateTotal(totalAmount,transactionType);
//If you pass a parameter, this for me is the best option.
activity.updateTotal(totalAmount,transactionType);
}
}
我同意@Alécio,请使用回调执行此操作。 在非活动类中添加一个回调接口:
class yourclass{
public interface callBack{
public void updateTotal(...);
}
private callBack callback;
public void registerCallback(callBack callback){
this.callback = callback;
}
//somewhere call the updateTotal(...)
callback.updateTotal(...);
}
在活动中
//the activity implement the callback and then register it, and call the callback when neccesary
class yourActivity extends Activity implement callBack{
@Override
onCreate(...){
...
yourclass.registerCallback(this);
}
@Override
public void updateTotal(...){
.......
}
}
多类通信的示例代码。
public class Controller {
callBack callBack;
public void registerCallBack(callBack back){
this.callBack = back;
}
public void show(){
callBack.update(1, "my name");
}
public interface callBack{
public void update(int type, String message);
}
public callBack getCallBack(){
return callBack;
}
}
public class AnotherClass {
Controller controller = new Controller();
public void registerCallBack(callBack back){
controller.registerCallBack(back);
}
public void show(){
controller.getCallBack().update(1, "show me!");
}
}
public class MyActivity extends Activity implements callBack {
AnotherClass myclass = new AnotherClass();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TAG", "This is message!");
setContentView(R.layout.main);
myclass.registerCallBack(this);
}
@Override
protected void onResume() {
super.onResume();
myclass.show();
}
@Override
public void update(int type, String message) {
((TextView) findViewById(R.id.display)).setText(message);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.