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

Posted

技术标签:

【中文标题】在处理程序上调用时为空文本视图【英文标题】:Null textview when it's call on a handler 【发布时间】:2018-11-25 18:30:10 【问题描述】:

我正在尝试在Handler 调用的Textview 上执行setText()(已经在onCreate() 中实例化)并使用ruiOnUiTread(),但我在@987654328 上有一个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 请求回调调用的函数启动

公共类 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);
        
    ;

【问题讨论】:

可能最好显示相关代码。 没有代码我们无法帮助您。阅读How to create a Minimal, Complete, and Verifiable example,可能在做最小的问题时,你会修复错误 我相信这个问题可能是因为你使用了不同的线程并且它在你的 onCreate 有机会初始化你的 textView 之前被执行 在调用 setText 之前尝试实例化你的 textview 问题解决了,是实例的问题 【参考方案1】:

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

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。您可以从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());

还有更多...

【讨论】:

【参考方案2】:

试试这个方法:

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

【讨论】:

以上是关于在处理程序上调用时为空文本视图的主要内容,如果未能解决你的问题,请参考以下文章

C++:在 OBJ、OBJ&、const OBJ& 上调用时实现不同的方法

IOS 8 iPad 应用程序在调用 UIActivityViewController 时崩溃

歌曲不可用时的警报视图

在直接调用委托的情况下如何减轻“访问修改的闭包”

Android 到服务器上的 Appengine RPC Nullponter

文本字段为空时隐藏自动完成表格视图