2015-01-17 13 views
5

में मैं इस तरह के TextView के रूप में एंड्रॉयड UI फ्रेमवर्क में विभिन्न दृश्य वर्गों पर प्रॉक्सी तरीकों की जरूरत है। विशेष रूप से TextView#setText(int resId)। यह विधि एक इंटरफ़ेस का हिस्सा नहीं है। इसलिए, जावा Proxy काम नहीं करेगा क्योंकि यह केवल इंटरफेस के लिए काम करता है। मुझे बाइटकोड मैनिपुलेशन का उपयोग करने की आवश्यकता है।प्रॉक्सी अंतिम विधि गैर अंतिम कक्षा

मैं एक पुस्तकालय dexmaker कहा जाता है कि होनहार लग रहा था मिल गया। मुझे लगता है कि मुझे रनटाइम बाइट कोड मैनिपुलेशन करने की आवश्यकता है क्योंकि एंड्रॉइड व्यू क्लासेस केवल डिवाइस पर उपलब्ध हैं। डेक्समेकर कंक्रीट कक्षाओं पर सार्वजनिक तरीकों का प्रॉक्सी कर सकता है। तब मैंने देखा कि TextView#setText(int resId) निष्पक्ष रूप से final है। TextView कक्षा स्वयं गैर-अंतिम है।

मुझे लगता है कि मैं गैर अंतिम कक्षाओं में अंतिम तरीकों का समर्थन करने के dexmaker कांटा सकता है। क्या यह संभव है? अगर यह नहीं है तो मैं इस परियोजना को शुरू नहीं करना चाहता हूं। यह मेरी लाइब्रेरी के लिए एक बड़ी जीत होगी हालांकि डेवलपर्स को उनके विचारों के लिए सबक्लास, इंटरफेस, या मैन्युअल स्थैतिक विधि कॉल करने की आवश्यकता नहीं होगी। मेरी लाइब्रेरी को यह जानने की जरूरत है कि जब विशेष दृश्य पर टेक्स्ट सेट किया जाता है। एक प्रॉक्सी इसके लिए एक आदर्श डिजाइन पैटर्न है।

+1

यादृच्छिक शॉट (चूंकि इसका उल्लेख नहीं किया गया है): एक लेआउट inflater [कारखाने वर्ग सेट करने की अनुमति देता है] (http://developer.android.com/reference/android/view/LayoutInflater। एचटीएमएल # setFactory2 (android.view.LayoutInflater.Factory2)) जो हो सकता है कि आप बाद में हो। इसका उपयोग [जांच] (https://github.com/lucasr/probe/) में किया जाता है जहां फैक्ट्री गतिशील रूप से कॉल को अवरुद्ध करने के लिए डेक्समेकर का उपयोग करके प्रॉक्सी बनाती है। –

+0

मेरी लाइब्रेरी का हिस्सा वास्तव में लेआउट inflater फैक्टरी तकनीक का उपयोग करता है। आप कह रहे हैं कि आप व्यू ऑब्जेक्ट्स पर प्रॉक्सी स्थापित कर सकते हैं जो डेक्समेकर के माध्यम से बनाए जाते हैं? – jophde

+0

बहुत बहुत धन्यवाद स्टीफन। जांच स्रोत बिल्कुल वही है जो मुझे चाहिए :)। अगर मैं सही ढंग से समझता हूं कि प्रोब पूरी तरह से नए व्यू क्लास बनाता है तो अंतिम विधियों को संभालने में सक्षम नहीं होने के कारण डेक्समेकर प्रॉक्सीबिल्ड सीमा कोई मुद्दा नहीं है? डेक्समेकर प्रॉक्सीबिल्डर डॉक्स से: "यह प्रक्रिया केवल सार्वजनिक और संरक्षित स्तर की दृश्यता वाले वर्गों के लिए काम करती है।" – jophde

उत्तर

2

जहां तक ​​मुझे पता है, एंड्रॉइड पर यह संभव नहीं है।

डेक्समेकर डेक्स फाइलें बनाता है जिसमें नई कक्षाएं होती हैं। इन कक्षाओं को तब डेक्स क्लास लोडर का उपयोग करके एक एप्लिकेशन में जोड़ा जाता है। ऐसी डीएक्स फाइलों का उपयोग कक्षाओं को प्रतिस्थापित करने के लिए नहीं किया जा सकता है, केवल नए उप-वर्गों को जोड़ने के लिए जो प्रॉक्सी के रूप में कार्य करते हैं।

इस अर्थ में, dexmaker बल्कि javassist से cglib की तरह है।

ध्यान दें कि एंड्रॉइड न तो नियमित जेवीएम के समान उपकरण क्षमता प्रदान करता है जहां आप एजेंट के माध्यम से कक्षा पुनर्वितरण द्वारा अंतिम कक्षाएं और विधियों का उपयोग कर सकते हैं। यह एंड्रॉइड द्वारा प्रदान नहीं किया गया है: http://developer.android.com/reference/android/app/Instrumentation.html

2

"अंतिम" की मंशा है कि विधि ओवरराइड नहीं किया जा सकता है। यह प्रभावी रूप से विस्तार से प्रॉक्सी करने के लिए रोक लगा देता है। हालांकि, आप अभी भी लपेटकर प्रॉक्सी कर सकते हैं, जिस तरह से वसंत इसे संभालता है।

एक कारण है कि यह एक सबसे अच्छा अभ्यास कार्यान्वयन से इंटरफेस अलग करने के लिए है कि।

अधिक ठोस संदर्भ में ...

// This snip is not supposed to be functional, only to demonstrate a concept 
interface TextViewInterface { 
    void setText (int resId); 
} 

class TextView implements TextViewInterface { 
    public final void setText (int resId) { 
    ... snip ... 
    } 
} 

class Proxy$TextView implements TextViewInterface 
extends View { // Added this for Android hierarchy 
    private TextView textView; 

    public void setText (int resId) { 
     textView.setText(resId); 
    } 
} 

इस मदद करता है?

+0

यह आम तौर पर काम करेगा लेकिन वस्तुओं को एंड्रॉइड व्यू ट्री पदानुक्रम में जाना होगा जो केवल व्यू या व्यू ग्रुप के उप-वर्ग स्वीकार करता है और मुझे यकीन है कि स्थानों में उदाहरण का उपयोग किया जाता है। यदि मैं TextView से विस्तार करता हूं तो क्या इंटरफ़ेस विधि क्लास विधि में हस्तक्षेप करेगी? – jophde

+0

हाँ यदि मैं TextView भी बढ़ाता हूं तो यह संकलित नहीं होगा। अगर वे केवल इंटरफेस का इस्तेमाल करते हैं ... – jophde

+0

इंटरफ़ेस तंत्र आपको कक्षा विधि को लपेटने की अनुमति देता है। आप व्यू को बढ़ा सकते हैं (इसे MyTextViewProxy पर कॉल करें) और टेक्स्ट व्यू को लपेटें, बशर्ते कुछ भी उपलब्ध हो, दृश्य स्वीकार्य है। मैंने विस्तार को देखने के लिए ऊपर दिए गए उदाहरण को अपडेट किया है। –

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