首页 > 解决方案 > 在处理程序上调用时为空文本视图

问题描述

我正在尝试setText()在 a调用的Textview(已经在 中实例化)上执行 a并使用,但我在.onCreate()HandlerruiOnUiTread()nullPointerExceptionTextview

问题可能来自哪里?

我在调试中看到实例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 请求回调调用的函数启动

公共类 StarterKillerPidroid {

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

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

}

邮递员类:

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

标签: javaandroidandroid-activityviewhandler

解决方案


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

FunctionalInterface是这种情况的好方法。

功能接口是只包含一个抽象方法的接口。它们只能展示一种功能。从 Java 8 开始,lambda 表达式可用于表示函数接口的实例。... Runnable、ActionListener、Comparable 是功能接口的一些示例。

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. 您可以从此处下载并导入您的项目。您还可以在此项目中做出贡献,以挽救许多开发人员的生命。

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

 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());

还有很多...


推荐阅读