当前位置: 首页 > 知识库问答 >
问题:

重复运行runOnUiThread()会导致异常

顾超
2023-03-14

(2016.3.15更新)

上周我遇到了一个奇怪的问题,我想和你讨论一下这个问题。

03-15 20:12:25.912/cn.example.app E/AndroidRuntime: FATAL EXCEPTION: Thread-10820  
   Process: cn.example.app, PID: 31532  
   java.lang.NullPointerException  
       at cn.example.app.homepage.GymFragment$searchThread.run(GymFragment.java:257)  
       at java.lang.Thread.run(Thread.java:841)  

但是,如果我使用sendMessage(SearchHandler.Object...)而不是runOnUiThread,一切都会很顺利!!

java:

@Override  
public void onActivityCreated(Bundle savedInstanceState){  
    super.onActivityCreated(savedInstanceState);
    new Thread(new SearchThread()).start();  
}  
class SearchThread implements Runnable{  
        @Override  
        public void run() {  
        String s = "";  
            try {  
                Thread.sleep(4000);  
            } catch (Exception e) {;}  
            //searchHandler.sendMessage(searchHandler.obtainMessage(0, s));//Correct   
            getActivity().runOnUiThread(new Runnable() { //Throw NullPointer Exception or pool-1-thread-1 (with ExecutorService) 
                @Override  
                public void run() {  
                    ;  
                }  
            });  
        }  
}  

SearchActivity.java:

class queryChangeListener implements SearchView.OnQueryTextListener{
    ...
    @Override
    public boolean onQueryTextChange(String newText) {
        currentSearchTip = newText;
        if (newText != null && newText.length() > 0) {
            searchDelayed(newText);
        }
        return true;
    }
}
private Handler searchHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        if (msg == null)
            return;
        String searchText = (String) msg.obj;
        if (currentSearchTip != null && currentSearchTip.isEmpty()==false) {
            GymFragment fragment = GymFragment.newInstance(searchText);
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment_layout, fragment).commit();
        }
    }
};
private ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(10);
private String currentSearchTip;
public void searchDelayed(String newText) {
    scheduledExecutor.schedule(new SearchThread(newText),500, TimeUnit.MILLISECONDS);
}
class SearchThread implements Runnable {
    String newText;
    public SearchThread(String newText){
        this.newText = newText;
    }
    public void run() {
        if (newText != null && newText.equals(currentSearchTip)) {
            searchHandler.sendMessage(searchHandler.obtainMessage(0, newText));
        }
    }
}

2)在运行getActivity().runonuithread()之前,首先判断getActivity()==null。

2016.3.14:

“一些有趣的事情:)”

    null
public final void runOnUiThread(Runnable action) {  
        if (Thread.currentThread() != mUiThread) {  
            mHandler.post(action);  
        } else {  
            action.run();  
        }  
}

让我们看看post(Runnable r)中有什么内容:

public final boolean post(Runnable r)  {    
       return  sendMessageDelayed(getPostMessage(r), 0);    
}   

并且在getPostMessage(Runnable r)中:

private final Message getPostMessage(Runnable r) {    
        Message m = Message.obtain();    
        m.callback = r;    
        return m;    
}   

然后在message.auttain()中:

public final Message obtainMessage()  {    
      return Message.obtain(this);    
}

public static Message obtain(Message orig) {    
       Message m = obtain();    
       m.what = orig.what;    
       m.arg1 = orig.arg1;    
       m.arg2 = orig.arg2;    
       m.obj = orig.obj;    
       m.replyTo = orig.replyTo;    
       if (orig.data != null) {    
           m.data = new Bundle(orig.data);    
       }    
       m.target = orig.target;    
       m.callback = orig.callback;    

       return m;    
}  

/**   
     * Return a new Message instance from the global pool. Allows us to   
     * avoid allocating new objects in many cases.   
     */    
public static Message obtain() {    
      synchronized (sPoolSync) {    
            if (sPool != null) {    
                Message m = sPool;    
                sPool = m.next;    
                m.next = null;    
                sPoolSize--;    
                return m;    
            }    
      }    
      return new Message();  
 }   

2、“sendmessage(消息msg)”的源代码:

public final boolean sendMessage(Message msg)  {    
       return sendMessageDelayed(msg, 0);    
}

在这里我们可以看到,sendMessage(Message msg)的实现几乎等同于post(Runnable r)的实现。差异可能与getPostMessage(Runnable r)相关联。

那么,简单地说,当我同时重复执行SearchHandler.SendMessage(SearchHandler.ObtainMessage(0,str))时,是什么实际导致正确执行SearchHandler.SendMessage(SearchHandler.ObtainMessage(0,str)),而导致getActivity().RunonUithRead(new Runnable{...})的异常呢?谢谢!

共有1个答案

包嘉懿
2023-03-14

我说不清为什么你的片段会脱离活动。但是如果您希望运行该代码而不考虑应用程序的状态,您可以简单地使用一个处理程序而不是RunonuithRead。只需确保在UI/Main线程中创建处理程序,所有对post()的调用都将导致Runnable在UI/Main线程上运行。

 类似资料:
  • 从我所读到的一切来看,它应该是可行的,但是以下几点: 在…内 不工作。与应用程序加载类似,但使用的是recyclingView\u Main。adapter=MainAdapter()似乎未运行。 完整代码: 正如您从上面的代码中看到的,当我将其放在onCreate中时,它工作得很好。 因此,问题似乎是将其发送到主线程。 XML

  • 我正在尝试向JavaFX应用程序添加一个标签,然而,每当我尝试制作标签时,都会得到一个错误。如果没有行,我不会出现任何错误,程序按预期工作。我能做些什么来解决这个问题吗? 我刚开始使用JavaFX,所以我知道的不多。 错误:

  • 问题内容: 我对Java线程技术比较陌生,并且我注意到,每次使用Thread.sleep()时,我都必须捕获InterrupetdException。 哪种行为会导致这种情况,并且在具有监视器线程的简单应用程序中,我可以忽略该异常吗? 问题答案: 好吧,如果其他一些线程调用thread.interupt(),则在该线程处于休眠状态时,您将获得Exception。是的,您可能只需将try..catc

  • 问题内容: 我想我发现了一个错误。也许不是,但是Super CSV不能很好地处理。 我正在使用MapReader解析具有41列的CSV文件。但是,我得到的是CSV- 而使我获得CSV的Web服务错了一行。“标题”行是制表符分隔的行,具有41个单元格。 而且“错误的行”是一个由制表符分隔的行,其中包含36个单元格,其内容没有任何意义。 这是我正在使用的代码: 我在上面提到的行中执行mapReader

  • 我在所有项目(平台共享)中将我的Xamarin. form包更新到最新(2.3.4.224),现在我似乎不应该再使用或枚举,因为它们已被弃用。 编译器因为这些行而抱怨: 上面写着: "Device.OS已过时。请改用Runtime平台" 到目前为止一切都很好,现在我想解决这个问题,我一直在尝试使用: 但它抛出了一个运行时异常。这是堆栈跟踪 04-08 14:57:34.812 I/MonoDroi

  • 以下操作会在运行时导致异常: java.lang.VerifyError:操作数堆栈上的类型错误异常详细信息:location:com/sun/net/httpserver/spi/httpserverprovider$1.run()ljava/lang/object;@27:invokestatic原因:类型“sun/net/httpserver/defaulthttpserverprovide