![]() |
![]() |
تداوم پیچیدگی اطلاعات
علاوه بر تداوم دیتا در bundle، اندروید ذخیره اطلاعات را با override کردن OnRetainNonConfigurationInstance و بازگشت نمونه از Java.Lang.Object که شامل تداوم دیتا می شود را پشتیبانی می کند.
2 هدف اصلی برای ذخیره حالت با استفاده از OnRetainNonConfigurationInstance وجود دارد:
1- آبجکت برگشت داده شده از OnRetainNonConfigurationInstance در مقیاس بزرگ و دیتا تایپ های پیچیده به خوبی انجام می شود و دلیل آن این است که حافظه آبجکت را بر می گرداند.
2- متد OnRetainNonConfigurationInstance طبق نیاز و تقاضا فراخوانی می شود که مقرون به صرفه تر از استفاده از یک کش دستی است.
استفاده از OnRetainNonConfigurationInstance برای سناریوهایی که برگرداندن دیتا در چندین دفعه هزینه بر است مانند فراخوانی وب سرویس ها مناسب است. نمونه کد زیر که در توییتر جستجو می کند را در نظر بگیرید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public class NonConfigInstanceActivity : ListActivity { protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); SearchTwitter ("xamarin"); } public void SearchTwitter (string text) { string searchUrl = String.Format("http://search.twitter.com/search.json?" + "q={0}&rpp=10&include_entities=false&" + "result_type=mixed", text); var httpReq = (HttpWebRequest)HttpWebRequest.Create (new Uri (searchUrl)); httpReq.BeginGetResponse (new AsyncCallback (ResponseCallback), httpReq); } void ResponseCallback (IAsyncResult ar) { var httpReq = (HttpWebRequest)ar.AsyncState; using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse (ar)) { ParseResults (httpRes); } } void ParseResults (HttpWebResponse httpRes) { var s = httpRes.GetResponseStream (); var j = (JsonObject)JsonObject.Load (s); var results = (from result in (JsonArray)j ["results"] let jResult = result as JsonObject select jResult ["text"].ToString ()).ToArray (); RunOnUiThread (() => { PopulateTweetList (results); }); } void PopulateTweetList (string[] results) { ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results); } } |
این کد نتیجه را به فرمت وب به صورت JSON بازمی گرداند، آن ها را Pars می کند و سپس آن ها را در یک لیست نمایش می دهد که در تصویر زیر قابل مشاهده است:
هنگامی که یک تغییر پیکربندی رخ می دهد(مانند rotate شدن گوشی) کد فرآیند را تکرار می کند. به منظور استفاده مجدد از نتایج اصل بازیابی می توان از OnRetainNonconfigurationInstance برای ذخیره نتیجه استفاده کرد مشابه زیر:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class NonConfigInstanceActivity : ListActivity { TweetListWrapper _savedInstance; protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); var tweetsWrapper = LastNonConfigurationInstance as TweetListWrapper; if (tweetsWrapper != null) { PopulateTweetList (tweetsWrapper.Tweets); } else { SearchTwitter ("xamarin"); } public override Java.Lang.Object OnRetainNonConfigurationInstance () { base.OnRetainNonConfigurationInstance (); return _savedInstance; } ... void PopulateTweetList (string[] results) { ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results); _savedInstance = new TweetListWrapper{Tweets=results}; } } |
حالا زمانی که دستگاه rotate می شود، نتایج اصلی از پراپرتی LastNonConfiguartionInstance باز می گردد. این نتایج شامل یک string[] به همرای توییت ها می باشد. تا زمانی OnRetainNonConfigurationInstance مورد نیاز است که Java.Lang.Object باز گردانده شود. string[] در کلاسی که زیر کلاسی از Java.Lang.Object است wrapped می شود.
1 2 3 4 5 6 7 8 9 |
class TweetListWrapper : Java.Lang.Object { public string[] Tweets { get; set; } } |
برای مثال تلاش برای استفاده از TextView به عنوان آبجکتی که از OnRetainNonConfigurationInstance بازگردانده می شود activity را نفوذپذیر می کند که در کد زیر نمایش داده شده است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
TextView _textView; protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); var tv = LastNonConfigurationInstance as TextViewWrapper; if(tv != null) { _textView = tv; var parent = _textView.Parent as FrameLayout; parent.RemoveView(_textView); } else { _textView = new TextView (this); _textView.Text = "This will leak."; } SetContentView (_textView); } public override Java.Lang.Object OnRetainNonConfigurationInstance () { base.OnRetainNonConfigurationInstance (); return _textView; } |