2011-03-07 44 views
1

我的Android代码中有一个事件处理机制,用于将传感器值转储到文件中。现在,我在主UI线程中执行它,因此UI按钮的响应速度非常缓慢,我想加快速度。如何在Android中使用多线程处理事件处理函数(SensorListeners)

如何在事件处理函数上使用多线程?我试图这样做:

  1. 创建一个全局变量writeNow。
  2. 当传感器值变化,设置WriteNow =真
  3. 在类中创建一个螺纹,其看起来像这样:

    Thread thread1 = new Thread() 
    { 
        public void run() 
        { 
        if(writeNow == true) 
         { 
         try 
         { 
          fos.write(s.getBytes()); 
         } 
         catch (IOException e) 
         { 
          e.printStackTrace(); 
         } 
         writeNow = false; 
         } 
        } 
    }; 
    

因此,每当writeNow是真实的,是将数据写入一个文件,然后将WriteNow设置为false。但是,我意识到这不是正确的方法,因为线程将执行一次,然后停止执行。当我用一段时间(true)和wait()尝试一个简单的例子时,我发现线程被中断了数百万次。

那么,如何将这个事件处理机制放在一个线程中,以加速进程呢?

谢谢!

回答

1

你可以尝试以下方法之一:

  1. 它看起来像你想保持运行所有的时间你写线程;你可以做的只是在你需要的时候产生线程。查看handling expensive operation in the UI thread的Android文档示例。

    下面是从页的例子:

    public class MyActivity extends Activity { 
    
        [ . . . ] 
        // Need handler for callbacks to the UI thread 
        final Handler mHandler = new Handler(); 
    
        // Create runnable for posting 
        final Runnable mUpdateResults = new Runnable() { 
         public void run() { 
          updateResultsInUi(); 
         } 
        }; 
    
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
    
         [ . . . ] 
        } 
    
        protected void startLongRunningOperation() { 
    
         // Fire off a thread to do some work that we shouldn't do directly in the UI thread 
         Thread t = new Thread() { 
          public void run() { 
           mResults = doSomethingExpensive(); 
           mHandler.post(mUpdateResults); 
          } 
         }; 
         t.start(); 
        } 
    
        private void updateResultsInUi() { 
    
         // Back in the UI thread -- update our UI elements based on the data in mResults 
         [ . . . ] 
        } 
    } 
    

    因为它看起来并不像你在UI线程做任何事情,一旦你写完你并不真的需要一个Handler打扰。但是一旦文件被写入,您可能想要使用它来显示Toast。另一方面,如果你仍然想要一个线程运行,你可能会有它sleep(),并定期醒来,并检查writeNow的状态。

    Thread thread1 = new Thread() 
    { 
        public void run() 
        { 
         while(true) 
         { 
          if(writeNow == true) 
          { 
           try 
           { 
            fos.write(s.getBytes()); 
           } 
           catch (IOException e) 
           { 
            e.printStackTrace(); 
           } 
    
           writeNow = false; 
          } 
    
          try 
          { 
           Thread.sleep(100); //sleep for 100 ms 
          } 
          catch (InterruptedException e) 
          { 
           Log.d('', e.getMessage()); 
          } 
         } 
        } 
    }; 
    

    注意,这会很快变得复杂,你可能会失去你希望在新的数据进来,当它醒来时,甚至较新的数据已经收到,并已覆盖了写,如果你的线程处于休眠状态字节前面的字节。你需要某种队列来管理它。

  2. 我不确定你在做什么与wait(),但应该也有效,实际上,这是涉及消费者和生产者的问题的方法。这个想法是让你的线程同步并在一个共享对象上(比如你的字节队列);当有数据可写并且写入器线程将被唤醒时,第二个线程将在共享对象上调用notify()。作者线程应该写入并重新写回。看看this tutorial

    至于你的线程中断,你的线程可能会中断一些原因这就是为什么它是很好的做法(特别是使用wait()时),以确保所定条件你你打电话之前,检查wait()仍因为您可能因拨打电话notify()/notifyAll()或因为中断而被唤醒。

+0

为什么我睡了100ms的?为什么不保持一段时间(真的)一直在运行?我实际上试过这段代码,但UI响应性根本没有改善...... – Imelza 2011-03-09 06:09:26

+0

如果你的线程没有“睡眠”(并且它不一定是100毫秒,这取决于你的应用程序),它不是给其他线程一个运行的机会 - 并且如果它是唯一占用所有系统资源的线程,那么您将在设备上看到一般的迟缓,因为UI线程和其他线程无法获得足够的CPU时间。看看[忙碌的等待](https://secure.wikimedia.org/wikipedia/en/wiki/Busy_waiting)。 – 2011-03-09 14:48:46

+0

您是否尝试了方法#1或#3? wait/notify'是消费者生产者问题的常用方法 - 请参阅我链接的教程。 #1中的代码非常完整,您只需将您的写入登录名移动到那里的'run()'方法中即可。如果这仍然没有帮助,那么你的问题在别处。 – 2011-03-09 14:51:22

0
Handler handler = null; 

handler = new Handler(); 

//create another class for and make consrtuctor as u want. so that u can use that effectively. 
//for example.              

popupIndex = new IndexThread(handler,head, target,ltp,price,IndexNifty.this,columsView,call);   

popupIndex.setColumnViewexit(columsView); 
handler.postDelayed(popupIndex, 300); 


//another class 
public IntraThread(Handler handler,String script,int target,int ltp,int price,Intraday intraday,TextView columsView,String call){ 
     super(); 
     this.target = target; 
     this.ltp = ltp; 
     this.price = price;  
     this.intraday = intraday; 
     this.columsView = columsView; 
     this.script= script; 
     this.handler= handler; 
     this.call= call; 
} 

public void run(){ 
// write ur code here.... 
} 
+0

另请参见[Acclerometer Sensor in Separate Thread](http://stackoverflow.com/a/17513504/192373) – 2013-10-03 09:47:42