Problem
A problem was encountered in the work:
Encapsulates an activity group that performs similar business a, but a small portion of the copy, picture is different, and requires that, during the execution of this group of activities, other businesses running in the background can modify the display at any time (or at the time of business a callback).
The less elegant options are:
-a reference to the activity passed in the callback. This limits the timing of the changes.
-Register the current activity in a single case and expose the corresponding modification interface on the activity. This is prone to memory leaks and requires other businesses to understand the various UI configurations/naming in Business a
In fact, this is a cross-activity MVVM problem, where both sides define good one model, and business A reads only the model content and works on the VM layer and the V layer. Other businesses only need to understand the model definition, hold the model and modify it.
The code has a binding function model
Public class Config { Public Static FinalString Action_config_change ="Gt.research.androidbase.ACTION_CONFIG_CHANGE"; Public Static FinalString Key_changed_parts ="Key_changed_parts";Private intMId;//just for convenient PrivateAtomicboolean mhascomsumed =NewAtomicboolean (true);//for Multithreading Private Finalthreadlocal<arraymap<string, object>> mtransactionmap =NewThreadlocal<> ();PrivateLocalbroadcastmanager Mbroadcastmanager;//model Private Finalarraymap<string, object> mconfigs =NewArraymap<> (); Public Config(intID) {mId = ID; }//multiple Changes PublicConfigBeginTransaction(Context context) {arraymap<string, object> map = Mtransactionmap.get ();if(NULL= = map) {map =NewArraymap<> (); } map.clear ();return This; } PublicConfigCommit(FinalContext context) {Finalarraymap<string, object> map = Mtransactionmap.get ();if(NULL= = map) {return This; }//for multi-threadingConfigmanager.getinstance (). Runonuithread (NewRunnable () {@Override Public void Run() {mconfigs.putall (map); Notifychange (context, (string[)) Map.keyset (). ToArray ()); } });return This; } PublicConfigSet(FinalContext Context,FinalString name,FinalObject object) {configmanager.getinstance (). Runonuithread (NewRunnable () {@Override Public void Run() {Mconfigs.put (name, object); Notifychange (context, name); } });return This; } PublicObjectGet(context context, String name) {//constrain on A if(Thread.CurrentThread ()! = Looper.getmainlooper (). GetThread ()) {Throw NewRuntimeException ("Wrong Thread"); }returnMconfigs.get (name); }//kvo PrivateConfigNotifychange(context context, String ... names) {Localbroadcastmanager Broadcastmanager = Getbroadcastmanager (context); Intent Intent =NewIntent (Action_config_change + mId); Intent.setpackage ("Gt.research.androidbase"); Intent.putextra (key_changed_parts, names); Broadcastmanager.sendbroadcast (Intent); Mhascomsumed.set (false);return This; }PrivateLocalbroadcastmanagerGetbroadcastmanager(Context context) {if(NULL= = Mbroadcastmanager) {Mbroadcastmanager = localbroadcastmanager.getinstance (context); }returnMbroadcastmanager; } Public Boolean shouldupdate() {return!mhascomsumed.getandset (true); } PublicString[]Getallnames() {return(string[]) Mconfigs.keyset (). ToArray (); }}
Public memory space
Public class configmanager { Private Static volatileConfigManager sinstance; Public StaticConfigManagergetinstance() {if(NULL= = Sinstance) {synchronized(Configmanager.class) {if(NULL= = sinstance) {sinstance =NewConfigManager (); } } }returnSinstance; }Private ConfigManager() { }Private FinalSparsearray<config> Mconfigs =NewSparsearray<> ();PrivateHandler Mhandler =NewHandler (Looper.getmainlooper ()); PublicConfigGetConfig(intID) {synchronized(Mconfigs) {Config config = mconfigs.get (id);if(NULL= = config) {config =NewConfig (ID); } mconfigs.put (id, config);returnConfig } } Public void Runonuithread(Runnable Runnable) {mhandler.post (runnable); }}
Business A
Public class main2activity extends appcompatactivity { PrivateTextView MText;Private intMId;PrivateString maction;//kvo PrivateBroadcastreceiver Mconfigreceiver =NewBroadcastreceiver () {@Override Public void OnReceive(context context, Intent Intent) {if(Maction.equals (Intent.getaction ())) {string[] changedparts = Intent.getstringarrayextra (config.key_changed_parts); Config config = configmanager.getinstance (). GetConfig (MId);if(Config.shouldupdate ()) {updateviews (changedparts, config); } } } };@Override protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (r.layout.activity_main2); MText = (TextView) Findviewbyid (R.ID.TEXT2); MId = Getintent (). Getintextra (mainactivity.key_id,-1);//a unique action just for this ActivityMaction = Config.action_config_change + mId;if(-1= = MId) {return; } localbroadcastmanager.getinstance ( This). Registerreceiver (Mconfigreceiver,NewIntentfilter (maction)); Config config = configmanager.getinstance (). GetConfig (MId);//fetch all missed changes if(Config.shouldupdate ()) {Updateviews (config.getallnames (), config); } }@Override protected void OnDestroy() {Super. OnDestroy (); Localbroadcastmanager.getinstance ( This). Unregisterreceiver (Mconfigreceiver); }Private void updateviews(string[] changedparts, config config) {String key = changedparts[0]; String value = (string) config.get ( This, key); Mtext.settext (value); }}
Other business
Public class mainactivity extends appcompatactivity { Public Static FinalString key_id ="id";Private intMId;@Override protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_main); Findviewbyid (R.id.text). Setonclicklistener (NewView.onclicklistener () {@Override Public void OnClick(View v) {mId = Math.Abs (NewRandom (System.currenttimemillis ()). Nextint ()); Intent Intent =NewIntent (mainactivity. This, Main2activity.class); Intent.putextra (key_id, mId); StartActivity (Intent);NewThread () {@Override Public void Run() {Try{Thread.Sleep ( +); Configmanager.getinstance (). GetConfig (MId). Set (mainactivity. This,"Lala","DLFJLAJF"); }Catch(Interruptedexception e) {E.printstacktrace (); }}}.start (); } }); }
Using Localbroadcast to achieve a cross-activity MVVM