如何从导入它的应用程序配置 Android 库?
How to configure Android library from an app that imports it?
我对 Android 开发有点陌生,所以我的问题可能很奇怪,甚至不可能。我不知道!
无论如何,我正在构建多个将具有大量共享元素的应用程序,因此我决定使用这些组件构建一个库并在所有应用程序中使用它,而不是愚蠢的复制和粘贴代码。
例如,库处理欢迎屏幕和 login/signup 流程活动等。所以这里是这种方法可能导致的问题:
- 虽然各个应用程序的行为相同,但我在欢迎屏幕上显示的徽标不同。现在我用图书馆资源 (R class) 中的图像资源填充它,这对所有应用程序都是一样的,显然是不正确的。
- login/signup 进程基于 Firebase,这将要求应用程序拥有密钥才能使用它们。现在我还用图书馆资源中的虚拟字符串资源填充它。
所以我的问题实际上可以归结为 3 个部分:
- 我是否可以将此信息从应用程序传递到图书馆?我可以以某种方式修改库的 R class 吗?或者我可以使用库中应用程序的 R class 吗?我也可以将库的这一部分作为传递我需要的参数的函数来调用。但第一个解决方案对我来说可能更干净?
- 无论问题 1 的答案是什么。我会在哪里以及如何做?图书馆有欢迎 activity 本身,这应该是应用程序中的第一个 activity。在应用程序启动后和第一个 activity 启动之前,如何以及在何处执行此操作?
- 如果我做的是错误的或不可能的,有没有其他方法可以实现它?
- Is there anyway I could pass this info from the app to the library?
can I somehow modify the R class of the library? Or can I use the
app's R class from the library? I can also call this part of the
library as a function passing the parameters I need. But the first
solution looks maybe more clean to me?
您不需要修改R class,因为您可以通过创建同名文件来覆盖资源文件。但这不是一个干净的解决方案,因为您经常需要确保您的项目和库资源名称相同。
- Whatever the answer to Q1 is. Where would I do this and how? The
library has the welcome activity itself which is supposed to be the
first activity in the app. How and where do I do this once the app
starts and before the first activity starts?
与其覆盖资源名称,不如修改您的库以接收配置作为使用该库的合同。这里的示例:
首先,创建class用于保存配置:
public class Configuration {
private int welcomeImageDrawableId;
private int logoDrawableId;
// constructor
public Configuration(int welcomeImageDrawableId, int logoDrawableId) {
this.welcomeImageDrawableId = welcomeImageDrawableId;
this.logoDrawableId = logoDrawableId;
}
// setter and getter.
public int getLogoDrawableId() {
return logoDrawableId;
}
}
其次,通过创建一个Singleton [=43=,为库使用配置class ] 将由图书馆内部使用:
public class MyLibrary {
private static MyLibrary myLibrary;
private Configuration configuration;
private MyLibrary(){}
private MyLibrary(Configuration configuration) {
this.configuration = configuration;
}
public static MyLibrary getInstance() {
if(myLibrary == null) {
throw new RuntimeException("Need call createInstanceWith method first!!");
}
return myLibrary;
}
public static MyLibrary createInstanceWith(Configuration configuration) {
if(myLibrary == null) {
synchronized(MyLibrary.class) {
if (myLibrary == null) {
myLibrary = new MyLibrary(configuration);
}
}
}
return test;
}
public Configuration getConfiguration() {
return configuration;
}
}
第三,通过单例class在你的库中使用配置class。像这样:
// assume imvLogo is an existing ImageView
Configuration configuration = MyLibrary.getInstance().getConfiguration();
imvLogo.setImageResource(configuration.getLogoDrawableId());
最后,当库使用时注册合约:
Configuration configuration = new Configuration(R.drawable.welcome, R.drawable.logo);
MyLibrary.createInstanceWith(configuration);
注意:所有代码尚未测试,错误在所难免。
除了上述解决方案之外,我还找到了另一种无需初始化库等即可实现这一切的方法。
我认为执行此操作的正确方法是在库中使用 productFlavors。这允许库共享一组主要的源代码、一组主要的资源,然后每个 app/flavors 共享一组额外的资源。这对我的目的来说已经足够了。
有关构建变体和风格的更多信息:
https://developer.android.com/studio/build/build-variants
我对 Android 开发有点陌生,所以我的问题可能很奇怪,甚至不可能。我不知道!
无论如何,我正在构建多个将具有大量共享元素的应用程序,因此我决定使用这些组件构建一个库并在所有应用程序中使用它,而不是愚蠢的复制和粘贴代码。 例如,库处理欢迎屏幕和 login/signup 流程活动等。所以这里是这种方法可能导致的问题:
- 虽然各个应用程序的行为相同,但我在欢迎屏幕上显示的徽标不同。现在我用图书馆资源 (R class) 中的图像资源填充它,这对所有应用程序都是一样的,显然是不正确的。
- login/signup 进程基于 Firebase,这将要求应用程序拥有密钥才能使用它们。现在我还用图书馆资源中的虚拟字符串资源填充它。
所以我的问题实际上可以归结为 3 个部分:
- 我是否可以将此信息从应用程序传递到图书馆?我可以以某种方式修改库的 R class 吗?或者我可以使用库中应用程序的 R class 吗?我也可以将库的这一部分作为传递我需要的参数的函数来调用。但第一个解决方案对我来说可能更干净?
- 无论问题 1 的答案是什么。我会在哪里以及如何做?图书馆有欢迎 activity 本身,这应该是应用程序中的第一个 activity。在应用程序启动后和第一个 activity 启动之前,如何以及在何处执行此操作?
- 如果我做的是错误的或不可能的,有没有其他方法可以实现它?
- Is there anyway I could pass this info from the app to the library? can I somehow modify the R class of the library? Or can I use the app's R class from the library? I can also call this part of the library as a function passing the parameters I need. But the first solution looks maybe more clean to me?
您不需要修改R class,因为您可以通过创建同名文件来覆盖资源文件。但这不是一个干净的解决方案,因为您经常需要确保您的项目和库资源名称相同。
- Whatever the answer to Q1 is. Where would I do this and how? The library has the welcome activity itself which is supposed to be the first activity in the app. How and where do I do this once the app starts and before the first activity starts?
与其覆盖资源名称,不如修改您的库以接收配置作为使用该库的合同。这里的示例:
首先,创建class用于保存配置:
public class Configuration {
private int welcomeImageDrawableId;
private int logoDrawableId;
// constructor
public Configuration(int welcomeImageDrawableId, int logoDrawableId) {
this.welcomeImageDrawableId = welcomeImageDrawableId;
this.logoDrawableId = logoDrawableId;
}
// setter and getter.
public int getLogoDrawableId() {
return logoDrawableId;
}
}
其次,通过创建一个Singleton [=43=,为库使用配置class ] 将由图书馆内部使用:
public class MyLibrary {
private static MyLibrary myLibrary;
private Configuration configuration;
private MyLibrary(){}
private MyLibrary(Configuration configuration) {
this.configuration = configuration;
}
public static MyLibrary getInstance() {
if(myLibrary == null) {
throw new RuntimeException("Need call createInstanceWith method first!!");
}
return myLibrary;
}
public static MyLibrary createInstanceWith(Configuration configuration) {
if(myLibrary == null) {
synchronized(MyLibrary.class) {
if (myLibrary == null) {
myLibrary = new MyLibrary(configuration);
}
}
}
return test;
}
public Configuration getConfiguration() {
return configuration;
}
}
第三,通过单例class在你的库中使用配置class。像这样:
// assume imvLogo is an existing ImageView
Configuration configuration = MyLibrary.getInstance().getConfiguration();
imvLogo.setImageResource(configuration.getLogoDrawableId());
最后,当库使用时注册合约:
Configuration configuration = new Configuration(R.drawable.welcome, R.drawable.logo);
MyLibrary.createInstanceWith(configuration);
注意:所有代码尚未测试,错误在所难免。
除了上述解决方案之外,我还找到了另一种无需初始化库等即可实现这一切的方法。 我认为执行此操作的正确方法是在库中使用 productFlavors。这允许库共享一组主要的源代码、一组主要的资源,然后每个 app/flavors 共享一组额外的资源。这对我的目的来说已经足够了。
有关构建变体和风格的更多信息: https://developer.android.com/studio/build/build-variants