自从Android引入库项目以来,我一直在将我的应用程序转换为库,以便我可以通过适当的调整制作几个版本(例如,使用相同代码库的免费版本和专业版本,但更改了一些东西)。
我最初在允许库项目的代码访问子项目中的字段时遇到了麻烦。换句话说,我的免费版和专业版都有一个类,里面有几个常量,库项目将使用这些常量来区分某些特性。
在子项目中,我扩展了库的主要活动,并添加了一个静态初始化块,该块使用反射来更改库中字段的值。
public class MyMainActivityProVersion extends MyMainActivity {
public static final String TAG = Constants.APP_NAME + "/SubClass";
static {
try {
ConstantsHelper.setConstants(Constants.class);
} catch (Exception e) {
Log.d(TAG, "--- Constants not initialised! ---");
e.printStackTrace();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
在这段代码中,ConstantsHelper在库中,我从我的子项目中提供了Constants.class。这将初始化库项目中的常量。
我的方法非常有效,除了一个特殊的用例。当应用程序有一段时间没有被使用并且被操作系统"停止"时,ConstantsHelper中的静态字段将被遗忘。
这些常量应该由主活动重置(如上所示),但是主活动甚至没有启动,因为操作系统恢复了一个不同的活动。这样做的结果是常量的初始化被遗忘,我不能重新初始化它们,因为恢复的活动在库中(它不知道子项目)。
我如何告诉库中的其他活动在恢复时从子项目调用代码?或者,是否有一种方法可以确保我的子项目中的一些代码在每个简历上都被调用?
我认为你试图通过静态成员在两个activity之间共享数据是在"作弊"。当它们位于相同或相关的类加载器中时,这恰好有效。在这里,我相信Android为单独的activity使用单独的类加载器,但是,子activity在子类加载器中。因此ViewActivity
恰好能够看到父类装入器并看到父类的静态信息。后来,我相信家长消失了,所以你的孩子重新加载MyMainActivity
本地当你下次访问它,它没有初始化你想要的。(好吧,如果不是那样的话,那就和这个解释很像了。)
我认为有一些更强大的替代方案。你可以使用LicenseChecker
API来决定你是在免费还是付费版本,而不是依赖于活动生命周期和类加载器的细节。这可能会更好,因为它可以保护您免受其他类型的未经授权的使用。
恐怕我从来没有找到这个问题的好答案。我可能会继续我对反射的糟糕使用,并找出一些hack的解决方法。
我觉得我应该回来,至少指出我没有为了其他人的利益而解决这个问题。
你可以使用Android资源来解决这个问题。基本上,在Library项目的资源xml值文件中定义常量
如。"自由计划" constants.xml值
<resources xmlns:tools="http://schemas.android.com/tools">
<bool name="const_free_version">false</bool>
<string name="const_a_constant">pippo</bool>
</resources>
然后,在子项目中,你可以使用不同的资源xml值文件重新定义lib-project的值:
如。"子工程" constants.xml值
<resources xmlns:tools="http://schemas.android.com/tools">
<bool name="const_free_version">true</bool>
</resources>
在你的lib项目代码中,当你引用R.bool。Const_free_version根据子项目常量值xml获得实际值。
注意,您不必重新定义库项目constants.xml中定义的每个值,只需重新定义子项目中需要的值。