froyo系统原生bug及修正:改变系统语言时Launcher2的AllApps内shortcut不刷新[转载]

转自:http://blog.csdn.net/zmyde2010/article/details/6598428

把froyo的Launcher2移植到eclair后,产生了一些小问题,都一一解决掉了.这是市场反馈回来的一个问题之一,摸清内部机制颇废了一番周折.也算见识了android系统内部的另一个面向切面编程案例,很有必要记录一下,有时间好好研究研究,可以借此做些特殊的系统功能. 

严格意义上说,这并不是跨版本移植产生的问题,而是系统原生的一个bug,用samsung的galaxy tab平板模拟器测试同样是此现象:当在Launcher里面启动Settings,改变语言设置后,再回到Launcher,AllApps2D里面的shortcuts文字部分并不随之更新,还是保持原样.其它部分却已更新. 

察看Settings源码可以知道,设置语言,改变的只是执行了如下代码: 
Java代码 
try {  
    IActivityManager am = ActivityManagerNative.getDefault();  
    Configuration config = am.getConfiguration();  
  
    Loc loc = mLocales[position];  
    config.locale = loc.locale;  
  
    // indicate this isn't some passing default - the user wants this remembered  
    config.userSetLocale = true;  
  
    am.updateConfiguration(config);  
    // Trigger the dirty bit for the Settings Provider.  
    BackupManager.dataChanged("com.android.providers.settings");  
} catch (RemoteException e) {  
    // Intentionally left blank  
}  
finish();  


在configuration改变后,系统会让每一个切换到前台的Activity destroy,然后重新加载至原位置,非常奇妙的刷新操作,有时间要看看他如何保存当前状态的代码,比如,当前切换到前台的Activity是launcher,则会一直加载到allapps2d打开,而不是oncreate完成后的初始位置.对于状态机学习来说,Launcher无疑是很好的教科书. 

然而,configuration的控制范围只是所有的Activity,Activity实现了一个接口ComponentCallbacks,里面有: 


Java代码 
/** 
* Called by the system when the device configuration changes while your 
* activity is running.  Note that this will <em>only</em> be called if 
* you have selected configurations you would like to handle with the 
* {@link android.R.attr#configChanges} attribute in your manifest.  If 
* any configuration change occurs that is not selected to be reported 
* by that attribute, then instead of reporting it the system will stop 
* and restart the activity (to have it launched with the new 
* configuration). 
*  
* <p>At the time that this function has been called, your Resources 
* object will have been updated to return resource values matching the 
* new configuration. 
*  
* @param newConfig The new device configuration. 
*/  
public void onConfigurationChanged(Configuration newConfig) {  
    mCalled = true;  
  
    if (mWindow != null) {  
        // Pass the configuration changed event to the window  
        mWindow.onConfigurationChanged(newConfig);  
    }  
}  


而对于Launcher来说,allapps里面的内容是通过LauncherModel.java里面的线程类去异步加载的,重启Launcher这个Activity,并不会让LauncherModel里面的缓存的allapps内容刷新,Launcher是直接拿了LauncherModel里面缓存的query数据而不是通知loader线程重新获取,问题就出在这里了. 

解决的方法并不复杂,Launcher在调onCreate()的时候,会调用checkForLocaleChange()方法检查是否语言设置是否被修改,我们定义一个boolean类变量,把语言设置是否改变存到里面,然后为LauncherModel重构一个startLoader方法,在onCreat()代码的相应位置调用此重构方法,把状态值传进去.在内部类Loader的loadAndBindAllApps()方法里,增加判断条件让语言改变时走loadAllAppsByBatch()路线即可. 

我们来看看可以从中学到些什么? 

1/定义和使用configuration的类变量,可以很好的传递任何全局数据,可以和硬件方便的通信. 
2/利用configuration控制framework各模块ui.一个简单例子,在launcher中,利用语言设置变化,显示或隐藏不同语言环境的应用,比如面向国内市场的机器,youtube反正用不上,就可以隐藏掉.加上youku.平板电脑没有phone功能的,把phone的shortcut给拿掉. 
3/另一个想法,能否利用configuration绕过系统权限实现截屏等需要root权限的功能?


  1. diff --git a/AndroidManifest.xml b/AndroidManifest.xml  
  2. old mode 100644  
  3. new mode 100755  
  4. index 28c0e0d..019c969  
  5. --- a/AndroidManifest.xml  
  6. +++ b/AndroidManifest.xml  
  7. @@ -74,6 +74,7 @@  
  8.              android:clearTaskOnLaunch="true"  
  9.              android:stateNotNeeded="true"  
  10.              android:theme="@style/Theme"  
  11. +            android:configChanges="locale"  
  12.              android:windowSoftInputMode="stateUnspecified|adjustPan">  
  13.              <intent-filter>  
  14.                  <action android:name="android.intent.action.MAIN" />  
  15. diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java  
  16. old mode 100644  
  17. new mode 100755  
  18. index e611303..f14d29f  
  19. --- a/src/com/android/launcher2/Launcher.java  
  20. +++ b/src/com/android/launcher2/Launcher.java  
  21. @@ -594,6 +594,15 @@ public final class Launcher extends Activity  
  22.      }  
  23.    
  24.      @Override  
  25. +    public void onConfigurationChanged(Configuration config) {  
  26. +        super.onConfigurationChanged(config);  
  27. +       checkForLocaleChange();  
  28. +       mModel.setAllAppsLoaded(false); // Set force load all apps list;  
  29. +       mModel.startLoader(thistrue); // Reload apps list  
  30. +   
  31. +    }  
  32. +  
  33. +    @Override  
  34.      protected void onPause() {  
  35.          super.onPause();  
  36.          mPaused = true;  
  37. diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java  
  38. old mode 100644  
  39. new mode 100755  
  40. index b819510..03a79dc  
  41. --- a/src/com/android/launcher2/LauncherModel.java  
  42. +++ b/src/com/android/launcher2/LauncherModel.java  
  43. @@ -95,6 +95,10 @@ public class LauncherModel extends BroadcastReceiver {  
  44.    
  45.      private Bitmap mDefaultIcon;  
  46.    
  47. +   public void setAllAppsLoaded(boolean load) {  
  48. +       mAllAppsLoaded = load;  
  49. +   }  
  50. +     
  51.      public interface Callbacks {  
  52.          public boolean setLoadOnResume();  
  53.          public int getCurrentWorkspaceScreen();  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值