2015-11-07 8 views
8

मैं एक बाधा में हूं। मैं निर्भरता इंजेक्शन के लिए डैगर 2 का उपयोग कर रहा हूं, लेकिन जब ऐप पृष्ठभूमि में जाता है तो मैं राज्य खो रहा हूं। यहां परिदृश्य है: ऐप शुरू होता है और निर्भरता बनाता है। जब तक ऐप अग्रभूमि में रहता है तब तक सभी काम पूरी तरह से काम करते हैं। हालांकि, एक परिदृश्य है जब ऐप को पृष्ठभूमि में जाना है। जब यह वापस आता है, तो मेरे इंजेक्शन वाले वर्गों में से एक में संग्रहीत मूल्य खो जाते हैं।डैगर 2 गतिविधि को रोकें और पुनर्स्थापित करें जब गतिविधि बंद हो जाती है

मेरे इंजेक्शन वाले वर्गों के लिए जिनकी कोई निर्भरता नहीं है, सबकुछ ठीक से ठीक हो रहा है। हालांकि, एक इंजेक्शन क्लास है जिसमें इंजेक्शन निर्भरता है, और यह वही है जो ठीक नहीं होता है। है यहाँ कैसे मैं इसे स्थापित करने हूँ अप:

AppComponent.java

@Singleton 
@Component(
    modules = { 
     AppModule.class 
    } 
) 

public interface AppComponent { 

    SessionKeyExchangerService provideSessionKeyExchangerService(); 
    AESCipherService provideCipherService(); 

    void inject(LoginActivity loginActivity); 
} 

AppModule.java

@Module 
public class AppModule { 

    @Provides @Singleton 
    AESCipherService provideCipherService() { 
     return new AESCipherService(); 
    } 

    @Provides @Singleton 
    SessionKeyExchangerService provideSessionKeyExchangerService(AESCipherService service) { 
     return new SessionKeyExchangerService(service); 
    } 
} 

और फिर जब मैं इन निर्भरताओं इंजेक्षन करने के लिए जाना, मैं यह कर इस तरह:

LoginActivity.java

@Inject 
SessionKeyExchangerService sessionKeyExchangerService; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_login); 

    Injector.INSTANCE.getAppComponent().inject(this); 

    if (savedInstanceState != null) { 
     sessionKeyExchangerService = savedInstanceState.getParcelable(SESSION_KEY_PARCEL); 
     Log.d(Constants.TAG, "session key retrieved in on create: " + sessionKeyExchangerService.getCipherService().getBase64EncodedSessionKey()); 
    } 
} 

तो, मेरे मौलिक सवाल है कि कैसे एक डैगर 2 इंजेक्शन वर्ग की राज्य बनाए रखना है। मुझे और कोड साझा करने में खुशी है, लेकिन यह आवश्यक विचार है।

किसी भी मदद के लिए धन्यवाद।

संपादित यह मानते हुए कि मैं क्या ऊपर किया है ठीक है, मुझे मैं कैसे बचा सकते हैं और उन इंजेक्शन वस्तुओं में संग्रहीत मूल्यों को पुनः प्राप्त करने पर बढ़ते हैं। यह दिखाएगा कि कहीं कोई समस्या है।

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

मेरा सबसे अच्छा अनुमान है कि मैं कहां गलत हो रहा हूं लॉग इन एक्टिविटी ऑनक्रेट में है जहां मैं सहेजे गए पार्सल से sessionKeyExchangerService मान को पुनर्स्थापित कर रहा हूं। मुझे लगता है कि मैं नए मान बना रहा हूं जो ऐप में इंजेक्शन निर्भरताओं के रूप में मान्यता प्राप्त नहीं हैं, लेकिन मुझे नहीं पता कि यह गलत क्यों है या इसे कैसे ठीक किया जाए।

इस कोड LoginActivity.java में भी है:

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putParcelable(SESSION_KEY_PARCEL, sessionKeyExchangerService); 
    Log.d(Constants.TAG, "session key saved: " + sessionKeyExchangerService.getCipherService().getBase64EncodedSessionKey()); 
} 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 
    super.onRestoreInstanceState(savedInstanceState); 
    sessionKeyExchangerService = savedInstanceState.getParcelable(SESSION_KEY_PARCEL); 
    Log.d(Constants.TAG, "session key retrieved in on restore state: " + sessionKeyExchangerService.getCipherService().getBase64EncodedSessionKey()); 
} 

यहाँ कंसोल आउटपुट कि मुद्दे को दर्शाता है। सूचना 1) कैसे onStop() के बाद पीआईडी ​​परिवर्तन कहा जाता है, और 2) कैसे वर्ग Authenticator (जो AESCipherService के लिए एक संदर्भ के लिए एक अलग सत्र कुंजी मान है है:

1398-1398/com.mysite.myapp डी/MYTAG: सहेजें उदाहरण स्थिति
1398-1398/com.mysite.myapp डी/MYTAG: सत्र कुंजी सहेजी गई: 93Zuy8B3eos + eCfBQk9ErA ==
1398-1398/com.mysite।MyApp डी/MYTAG: स्टॉप पर
3562-3562/com.mysite.myapp डी/MYTAG: सत्र कुंजी में लिया गया पर बनाने के लिए: 93Zuy8B3eos + eCfBQk9ErA ==
3562-3562/com.mysite.myapp डी/MYTAG:
3562-3562/com.mysite.myapp डी/MYTAG पर: सत्र कुंजी पुनर्स्थापित स्थिति में पुनर्प्राप्त: 93Zuy8B3eos + eCfBQk9ErA ==
3562-3562/com.mysite.myapp डी/MYTAG: प्रमाणीकरणकर्ता वर्ग कहता है कि सत्र कुंजी है: 28HwdRCjBqH3uFweEAGCdg ==

SessionKeyExchangerService.java

protected SessionKeyExchangerService(Parcel in) { 
     notifyOn = in.readString(); 
     sessionKeyExchangeAttempts = in.readInt(); 
     MAX_SESSION_KEY_EXCHANGE_ATTEMPTS = in.readInt(); 
     sessionKeyExchangeHasFailed = (in.readByte() == 1); 
     cipherService = in.readParcelable(AESCipherService.class.getClassLoader()); 
    } 

    public static final Creator<SessionKeyExchangerService> CREATOR = new Creator<SessionKeyExchangerService>() { 
     @Override 
     public SessionKeyExchangerService createFromParcel(Parcel in) { 
      return new SessionKeyExchangerService(in); 
     } 

     @Override 
     public SessionKeyExchangerService[] newArray(int size) { 
      return new SessionKeyExchangerService[size]; 
     } 
    }; 

@Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeString(notifyOn); 
     dest.writeInt(sessionKeyExchangeAttempts); 
     dest.writeInt(MAX_SESSION_KEY_EXCHANGE_ATTEMPTS); 
     dest.writeByte((byte) (hasSessionKeyExchangeFailed() ? 1 : 0)); 
     dest.writeParcelable(cipherService, flags); 
    } 

AESCipherService.java

protected AESCipherService(Parcel in) { 
    sessionKeyBytes = in.createByteArray(); 
    ivBytes = in.createByteArray(); 
    sessionId = in.readLong(); 
    mIsSessionKeyEstablished = (in.readByte() == 1); 
    verbose = (in.readByte() == 1); 
} 

public static final Creator<AESCipherService> CREATOR = new Creator<AESCipherService>() { 
    @Override 
    public AESCipherService createFromParcel(Parcel in) { 
     return new AESCipherService(in); 
    } 

    @Override 
    public AESCipherService[] newArray(int size) { 
     return new AESCipherService[size]; 
    } 
}; 

@Override 
public void writeToParcel(Parcel dest, int flags) { 
    dest.writeByteArray(sessionKeyBytes); 
    dest.writeByteArray(ivBytes); 
    dest.writeLong(sessionId); 
    dest.writeByte((byte) (isSessionKeyEstablished() ? 1 : 0)); 
    dest.writeByte((byte) (verbose ? 1 : 0)); 
} 
+1

आप जहाँ आप अपने गतिविधि इंजेक्षन और भी जहां ग्राफ निर्माण कर रहे हैं कोड दे सकते हैं? – Ognyan

+0

मैं अंततः इस सवाल पर वापस आ रहा हूं। मैंने इस सवाल पर फिर से लिखा कि मैं पार्ससेल के बजाए निर्भरता इंजेक्शन कैसे स्थापित करता हूं। मुझे पूरा भरोसा है कि मैं इसका सही हिस्सा कर रहा हूं, इसलिए त्रुटि को डगर 2 भाग में होना चाहिए। – Alex

+0

मेरा मानना ​​है कि आप '()' onSaveInstanceState के माध्यम से आप अपने मॉड्यूल में प्रदान की राज्य को क्रमानुसार और यह 'onRestoreInstanceState में वापस हैक करने की आवश्यकता होगी()', प्रक्रिया मौत पर विचार पूरे आवेदन प्रक्रिया को मारता है और केवल बंडलों जीवित रहते हैं। आपको संभवतः 'onRestoreInstanceState()' में अपना घटक बनाने की आवश्यकता होगी यदि यह अस्तित्व में नहीं है, और घटक की प्रावधान विधियों के माध्यम से अपनी निर्भरताओं को तुरंत चालू करके इसे एक बार में वापस रख दें। – EpicPandaForce

उत्तर

1

इंजेक्शन मूल्यों का मतलब यह है कि आप अपने आप को मूल्य नहीं देते। यह कहा गया,

@Inject 
SessionKeyExchangerService sessionKeyExchangerService; 

// then in onCreate() after the injection 
sessionKeyExchangerService = savedInstanceState.getParcelable(SESSION_KEY_PARCEL); 

वह नहीं है जो आप करना चाहते हैं।

अपने SessionKeyExchangerService कुछ बचाया राज्य पर निर्भर करता है, तो आप इसे अपने मॉड्यूल में पारित करना होगा।

AppModuleSessionKeyExchangerService प्रदान करने के लिए गलत जगह हो रहा है। आपको शायद SessionModule पर आउटसोर्स करना चाहिए, जिसे आप स्वैप कर सकते हैं, जैसा कि मुझे लगता है कि well explained here है। इस नमूने में, उपयोगकर्ता मॉड्यूल लाइफसाइक्ल ऐप द्वारा प्रबंधित किया जाता है, और डैगर नहीं।

एक निर्माता के साथ एक मॉड्यूल प्रदान करके आप savedInstanceState से अपने Parcelable स्थिति में प्रवेश कर सकते हैं।

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

+0

धन्यवाद। 'सत्र KeyExchangerService' वास्तव में' एईएससीफर सेवा 'पर निर्भरता के अलावा कोई राज्य नहीं है। मैंने मूल रूप से सिंगलटन ऑब्जेक्ट्स बनाने के तरीके के रूप में निर्भरता इंजेक्शन चुना जो थ्रेडसेफ थे।मैं 'साझा किए गए संदर्भ' का उपयोग नहीं कर सकता क्योंकि ऐसा करने से मुझे डिस्क पर क्रिप्टो कुंजी स्टोर करने के लिए मजबूर किया जाएगा, और मैं चाहता हूं कि कार्यक्रम होने पर इन्हें दूर जाना पड़े। मैंने यह नहीं देखा कि जब मैं शुरू हुआ था तो मैं एक राज्य की स्थिति बनाउंगा या शायद मैं इसे स्थिर तरीके से कक्षा में रखूंगा। मुझे इसके लिए एक कामकाज मिला, लेकिन यह हैकी की तरह है। अंततः इन निर्भरताओं को दूर करने के लिए मुझे अपने कोड – Alex

+0

को दोबारा प्रतिक्रिया देना पड़ सकता है। मुझे लगता है कि मैंने निष्कर्ष निकाला है कि निर्भरता इंजेक्शन इस मामले में आदर्श वास्तुशिल्प निर्णय नहीं था। लाइव और जानें ... उत्तर के लिए धन्यवाद। – Alex

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

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