2011-10-13 6 views
21

मुझे कुछ यूआई अपडेट करने और यूआई थ्रेड के अंदर इसे runOnUiThread
का उपयोग करके करने की आवश्यकता है अब यूआई के लिए डेटा अन्य थ्रेड से आता है, जो data द्वारा दर्शाया गया है।
एंड्रॉइड - runOnUiThread में रननेबल को डेटा कैसे पास करें?

मैं रननेबल को डेटा कैसे पास कर सकता हूं, तो क्या यूआई को अपडेट करने के लिए उनका उपयोग किया जा सकता है? एंड्रॉइड सीधे डेटा का उपयोग करने की अनुमति नहीं देता है। क्या ऐसा करने का कोई शानदार तरीका है?

public void OnNewSensorData(Data data) { 

    runOnUiThread(new Runnable() { 
     public void run() { 
      //use data 
     } 
    }); 
} 

मेरे समाधान runnable के अंदर एक fioeld private Data sensordata बनाने था, और यह करने के लिए डेटा बताए। यह केवल तभी काम करता है, यदि मूल Data data अंतिम है।

public void OnNewSensorData(final Data data) { 

    runOnUiThread(new Runnable() { 
     private Data sensordata = data; 
     public void run() { 
      //use sensordata which is equal to data 
     } 
    }); 
} 

उत्तर

35

समस्या आप में पाया गया कि जावा कब्जा में

इनर वर्गों ("पर बंद") शाब्दिक है जिस क्षेत्र में परिभाषित किया गया है। लेकिन वे केवल चर को कैप्चर करते हैं जिन्हें "अंतिम" घोषित किया जाता है।

यदि यह कीचड़ के रूप में स्पष्ट है, वहाँ जानकारी यहां की एक अच्छी चर्चा है: Cannot refer to a non-final variable inside an inner class defined in a different method

लेकिन अपने समाधान ठीक लग रहा है।इसके अलावा, बशर्ते कि data अंतिम है, तो आप इस के लिए कोड को आसान बनाने में कर सकते हैं:

public void OnNewSensorData(final Data data) { 
    runOnUiThread(new Runnable() { 
     public void run() { 
      // use data here 
      data.doSomething(); 
     } 
    }); 
} 
1

आप हर बार अपने कार्यक्रम नई Data यह दिखाना चाहता है है को अपडेट करना होगा। यहां आपका दूसरा कोड सूची इसे पूरा करने का मानक तरीका है। यदि आप थ्रेड में Data अपडेट करना जारी रखते हैं तो कुछ कैच हो सकते हैं। यदि यह मामला तब तक थ्रेड को अवरुद्ध करने पर विचार करता है जब तक यूआई डेटा को अद्यतन करने या प्रतिलिपि को Data ऑब्जेक्ट पर कॉपी नहीं करता है।

आंतरिक रूप से क्या हो रहा है यह है कि जेवीएम अज्ञात वर्ग चलाने के लिए Data ऑब्जेक्ट के संदर्भ की प्रतिलिपि बना रहा है। अंदर संग्रहीत Data अभी भी बदला जा सकता है। यदि आपकी विधि को Data में अतिरिक्त परिवर्तन की आवश्यकता है तो बस एक और चर (ऑब्जेक्ट संदर्भ) का उपयोग करें जैसे: final Data finalData = data;। आप लाइन private Data sensordata = data; भी हटा सकते हैं और सीधे अपने रन विधि में डेटा का उपयोग कर सकते हैं।

यह सुरुचिपूर्ण दिखाई नहीं दे सकता है, लेकिन इस तरह जावा अज्ञात कक्षाओं में ऑब्जेक्ट चर को पास करता है। वहाँ जावा भाषा संस्करण 7 में नए वाक्य रचना है, लेकिन एंड्रॉयड जावा भाषा संस्करण 5 और के साथ संगत है 6.

20

आप (के रूप में दान एस द्वारा वर्णित) एक मध्यवर्ती अंतिम चर का उपयोग कर, आप एक अतिरिक्त विधि के साथ Runnable लागू कर सकते हैं बचना चाहते हैं डाटा सेट करने के लिए:

public void OnNewSensorData(Data data) { 
    MyRunnable runnable = new MyRunnable(); 
    runnable.setData(data); 
    runOnUiThread(runnable); 
} 

आप भी MyRunnable के निर्माता Dat में ले कर सकता है:

public class MyRunnable implements Runnable { 
    private Data data; 
    public void setData(Data _data) { 
    this.data = _data; 
    } 

    public void run() { 
    // do whatever you want with data 
    } 
} 

फिर आप इस तरह विधि कॉल कर सकते हैं एक तर्क के रूप में एक उदाहरण:

public class MyRunnable implements Runnable { 
    private Data data; 
    public MyRunnable(Data _data) { 
    this.data = _data; 
    } 

    public void run() { 
    ... 
    } 
} 

और फिर बस runOnUiThread कहना (नई MyRunnable (डेटा));

0
public static Activity globalContext = null;  
CommonSetting.globalContext = this;// put this in MainACtivity.onCreate() 
public void createToastShort(final String message) { 
    runOnUiThread(new Runnable() { 
     public void run() { 
     Toast.makeText(CommonSetting.globalContext, message, Toast.LENGTH_SHORT).show(); 
     } 
    }); 
} 
5

मुझे ऐसी ही समस्या थी जहां मैं थ्रेड में जानकारी पास करना चाहता था। एंड्रॉयड प्रणाली के साथ इसे हल करने के लिए, मैं में corsiKa के जवाब को संशोधित: Runnable with a parameter?

आप विधि में एक वर्ग सही घोषित करने और परम पारित कर सकते हैं जैसा कि नीचे दिखाया:

void Foo(String str) { 
    class OneShotTask implements Runnable { 
     String str; 
     OneShotTask(String s) { str = s; } 
     public void run() { 
      someFunc(str); 
     } 
    } 
    runOnUiThread(new OneShotTask(str)); 
} 
1

यहाँ एक विशिष्ट मामले जहां सेवा है कॉलबैक को यूआई स्टेटस स्ट्रिंग (टेक्स्ट व्यू टेक्स्टस्टैटस) अपडेट करने के लिए बुलाया जाता है। सेवा थ्रेडेड हो सकती है।

नमूना को जोड़ती है पता चल सके कि धागा पुनर्निर्देशन की जरूरत है और वास्तविक पुनर्निर्देशन:

// service callbacks 
    public void service_StatusTextChanged(final String s) { 
     if(isOnUiThread()) { 
      textStatus.setText(s); 
     } else { 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        textStatus.setText(s); 
       } 
      }); 
     } 
    } 

    static public boolean isOnUiThread() { 
     return Thread.currentThread() == Looper.getMainLooper().getThread(); 
    } 

भी देखें How to check if running on UI thread in Android?

संबंधित मुद्दे