在处理程序上调用时为空文本视图
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());
还有更多...
我正在尝试对由 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());
还有更多...