2017-02-22 8 views
8

नीचे वर्ग एक बहुत ही अनोखी जीवन चक्र है, जो मुझे आवश्यकता है अस्थायी रूप से बाहर अशक्त lateinit गुणlateinit Kotlin संपत्ति शून्य पर सेट करने के लिए कैसे

class SalesController : BaseController, SalesView { 
    @Inject lateinit var viewBinder: SalesController.ViewBinder 
    @Inject lateinit var renderer: SalesRenderer 
    @Inject lateinit var presenter: SalesPresenter 
    lateinit private var component: SalesScreenComponent 

    override var state = SalesScreen.State.INITIAL //only property that I want to survive config changes 

    fun onCreateView(): View { /** lateinit variables are set here */ } 
    fun onDestroyView() { 
     //lateinit variables need to be dereferences here, or we have a memory leak 
     renderer = null!! //here's the problem: throws exception bc it's a non-nullable property 

} }

यहाँ है कि यह कैसे ढांचे द्वारा प्रयोग किया जाता है के लिए है ।

controller.onCreateView() //same instance of controller 
controller.onDestroyView() //same instance of controller 
controller.onCreateView() //same instance of controller 
controller.onDestroyView() //same instance of controller 

मेरे lateinit गुण चाकू से इंजेक्ट किया जाता है, और मैं onDestroyView में null करने के लिए उन्हें निर्धारित करने की आवश्यकता है - या एक स्मृति रिसाव है। हालांकि यह कोटलिन में संभव नहीं है, जहां तक ​​मुझे पता है (प्रतिबिंब के बिना)। मैं इन गुणों को निरर्थक बना सकता हूं, लेकिन यह कोटलिन की शून्य सुरक्षा के उद्देश्य को हरा देगा।

मुझे यकीन नहीं है कि इसे कैसे हल किया जाए। आदर्श रूप से कुछ प्रकार का एनोटेशन प्रोसेसर हो सकता है जो onDestroyView में स्वचालित चर को स्वचालित रूप से निकालने के लिए जावा कोड उत्पन्न करेगा?

+0

आपके पास रिसाव क्यों है? हो सकता है कि समस्या इसके गुणों की बजाय SalesController पर है? मुझे लीक समस्याओं से बचने के लिए डैगर द्वारा इंजेक्शन वाली संपत्ति को स्पष्ट रूप से सेट करने की आवश्यकता नहीं है ... – Massimo

+0

@ मासिमो कंडक्टर के नियंत्रक उदाहरण कॉन्फ़िगरेशन परिवर्तनों में जीवित रहते हैं https://github.com/bluelinelabs/Conductor – ZakTaccardi

+0

यदि आपको उन्हें निरस्त करने की आवश्यकता है, तब आपको 'देर से' रखने की आवश्यकता नहीं है। और मुझे पूरा यकीन है कि आपके पास कोई रिसाव नहीं है, आप बस कुछ परिभाषाओं को मिला रहे हैं। यदि आपका प्रेजेंटर आपके व्यू को संदर्भित करेगा, तो आप रिसाव करेंगे, विपरीत नहीं – Dimezis

उत्तर

7

Kotlin lateinit गुण एक गैर-आरंभिकृत झंडा मूल्य के रूप में null उपयोग करते हैं, और वहाँ प्रतिबिंब के बिना एक lateinit संपत्ति के समर्थन क्षेत्र में null स्थापित करने के लिए कोई साफ रास्ता नहीं है।


हालांकि, कोटलिन आपको प्रतिनिधि गुणों का उपयोग करके गुण व्यवहार को ओवरराइड करने की अनुमति देता है। लगता है कोई प्रतिनिधि है कि kotlin-stdlib में, लेकिन अगर आप वास्तव में इस व्यवहार की जरूरत है, तो आप implement your own delegate ऐसा करने के लिए कर सकते हैं अनुमति देता है वहाँ की तरह, अपने utils के लिए कुछ कोड जोड़ने:

class ResettableManager { 
    private val delegates = mutableListOf<ResettableNotNullDelegate<*, *>>() 

    fun register(delegate: ResettableNotNullDelegate<*, *>) { delegates.add(delegate) } 

    fun reset() { delegatesToReset.forEach { it.reset() } } 
} 

class Resettable<R, T : Any>(manager: ResettableManager) { 
    init { manager.register(this) } 

    private var value: T? = null 

    operator fun getValue(thisRef: R, property: KProperty<*>): T = 
      value ?: throw UninitializedPropertyAccessException() 

    operator fun setValue(thisRef: R, property: KProperty<*>, t: T) { value = t } 

    fun reset() { value = null } 
} 

और उपयोग:

class SalesController : BaseController, SalesView { 
    val resettableManager = ResettableManager() 
    @set:Inject var viewBinder: SalesController.ViewBinder by Resettable(resettableManager) 
    @set:Inject var renderer: SalesRenderer by Resettable(resettableManager) 
    @set:Inject var presenter: SalesPresenter by Resettable(resettableManager) 

    fun onDestroyView() { 
     resettableManager.reset() 
    } 
} 
+0

मुझे नहीं लगता था कि आप 'सदस्य संपत्ति के साथ सदस्य संपत्ति' पर 'इंजेक्ट 'कर सकते हैं। – mfulton26

+0

@ mfulton26, टिप्पणी के लिए धन्यवाद! क्या आपको लगता है कि यह '@set: इंजेक्ट' के साथ काम करेगा? – hotkey

+0

अच्छी सोच। मुझे लगता है कि यह होगा (मैं डैगर या कुछ भी नहीं कर रहा हूं लेकिन कम से कम संकलित करता हूं)। – mfulton26

0

मुझे लगता है कि तुम क्या जरूरत है एक सामान्य स्वस्थ nullablelateinit की madgic बिना संपत्ति है:

class SalesController : BaseController, SalesView { 
    @Inject @JvmField var viewBinder: SalesController.ViewBinder? = null 

इस समाधान संकलक के साथ आप यह जांचने के लिए कहेंगे कि viewBindernull है या नहीं, लेकिन आईएमओ यह उचित है क्योंकि यह आपके कार्यक्रम के किसी भी बिंदु पर null बन सकता है।

+0

को अनदेखा करता है, यह काम नहीं करता है, क्योंकि कुछ गुणों को हमेशा 'ऑनक्रेट व्यू'/'ऑनडिस्ट्रोव्यू' स्कोप के भीतर गैर-शून्य नहीं होना चाहिए, जबकि अन्य गुण वास्तव में उस दायरे में शून्य हो सकते हैं। अगर सब कुछ शून्य है, तो मेरे पास दोनों के बीच अंतर करने का कोई तरीका नहीं है और हम फिर से जावा की शून्य सुरक्षा समस्या पर वापस आ गए हैं – ZakTaccardi

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