在处理程序上调用时为空文本视图

Null textview when it's call on a handler

我正在尝试对由 Handler 调用的 Textview(已在 onCreate() 中实例化)执行 setText() 并使用 ruiOnUiTread() 但我在 Textview.

上有一个 nullPointerException

问题出在哪里?

我在调试中看到 activity 的实例在实例化和 setText() 之间不相同,而我没有更改 activity 但不可能在相同的实例化它放置为 setText().

private TextView ambianceTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ambianceTextView = findViewById(R.id.valeur_ambiance);

    StarterKillerPidroid.getInstance().startApp();
}

private final Runnable retrieveData = new Runnable() {
    public void run() {
        try {
            setText();
        } catch (Exception e) {
            e.printStackTrace();
        }
        handlerRecup.postDelayed(retrieveData, 1000);
    }
};

public void setText(){
  runOnUiThread(new Runnable() {
     @Override
     public void run() {
        ambianceTextView.setText("test");
     }
   });
}

public void doAfterLogin() {
    handlerRecup.postDelayed(retrieveData, 10000);
}

runnable 由使用 Volley 的 http 请求回调调用的函数启动

public class StarterKillerPidroid {

void startApp() {
    //Sending a request 
    PostmanPidroid.getInstance().login();
}

public void ackLogin(Boolean isValid) {
    if (isValid) {
        ActivityMain.getInstance().doAfterLogin();
    } else {
        PostmanPidroid.getInstance().login();
    }
}

}

class邮递员:

  public class Postman {
   public void login(){

        // Parameters
        String email = "test@tes";
        String password = "test";

        // Encoding the request with parameters
        JsonObjectRequest request = EncoderDecoderPidroid.getInstance()
                .encodeRequestLogin(email, password);

        // Sending the request
        sendRequest(request);
     }

     void sendRequest(StringRequest message){
         // Creating the queu if it's not create
         if (queue == null) {
               queue = Volley.newRequestQueue(context);
          }
          // Adding the request to the queue
              queue.add(message);
           }
   }

收到成功响应后,将调用此回调:

 private Response.Listener<JSONObject> callbackLogin =
            new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            ...
            StarterKillerPidroid.getInstance().ackLogin(true);
        }
    };

试试这个方法:

private final Runnable retrieveData = new Runnable() {
    public void run() {
        try {
            ambianceTextView = (TextView) findViewById(R.id.valeur_ambiance);
            setText();
        } catch (Exception e) {
            e.printStackTrace();
        }
        handlerRecup.postDelayed(retrieveData, 1000);
    }
};

基本上这种问题都是实例造成的。您的 textview 实例可能未初始化。直接使用处理程序更新 UI 线程的另一件事不是一个好主意。您应该使用 FunctionalInterface 来执行此操作,而不是直接使用处理程序更新 Ui。

FunctionalInterface 是这种情况的好方法。

A functional interface is an interface that contains only one abstract method. They can have only one functionality to exhibit. From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface. ... Runnable, ActionListener, Comparable are some of the examples of functional interfaces.

Java 有预定义的 FunctionalInterface Callable。它是这样的

public static void doDid(final Callable<Void> callable) {
    final Handler handler = new Handler();

    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            try {
                callable.call();
                handler.postDelayed(this, every * repeattime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }, every * tempvalue);
}

并使用它以这种方式更新 UI

 doDid(new Callable<Void>() {
                    @Override
                    public Void call() {
                         textView.setText("Your text");
                        return null;
                    }
                });

Android 有一个可用的开源库,它的工作原理就像一个叫做 Predictor 的案例。您可以从 here 下载它并导入到您的项目中。您也可以在这个项目中做出贡献,以挽救许多开发人员的生命。

你想看看预测器是如何做到这一点的吗?

 Predictor.every(3).second().doDid(new Job<Void>() {
                    @Override
                    public Void run() {
                        textView.setText("Your text");
                        return null;
                    }
                });

你能用预测器做什么?

Predictor 为您提供了几种处理多线程的方法,其中一些方法如下:

Predictor.every(3).second().doDid(something());
Predictor.every(5).minutes().doDid(something());
Predictor.every().hour().doDid(something());
Predictor.every().week().doDid(something());
Predictor.every().month().doDid(something());

还有更多...