Java 如何在单例中处理远程配置实例
我试图做的是对一个远程配置获取进行单例处理,以便第一次在我的SplashScreen中加载它 当我的splashscreen加载时,我用远程配置单例获取数据一次,然后,我只访问每个类中需要远程配置值的值 我这样做是为了防止用户在活动中看到更改,这是因为我制作了一个圣诞节主题,以显示带有远程配置的自定义布局 一切都很好(有时),主题在整个应用程序中都发生了变化,但有时在我的SplashScreen加载后,异步获取时间必须返回,因此我可以在我的其余活动中看到主题的变化,但在SplashScreen加载后的主活动中看不到 这是我的单身汉Java 如何在单例中处理远程配置实例,java,android,firebase,firebase-remote-config,Java,Android,Firebase,Firebase Remote Config,我试图做的是对一个远程配置获取进行单例处理,以便第一次在我的SplashScreen中加载它 当我的splashscreen加载时,我用远程配置单例获取数据一次,然后,我只访问每个类中需要远程配置值的值 我这样做是为了防止用户在活动中看到更改,这是因为我制作了一个圣诞节主题,以显示带有远程配置的自定义布局 一切都很好(有时),主题在整个应用程序中都发生了变化,但有时在我的SplashScreen加载后,异步获取时间必须返回,因此我可以在我的其余活动中看到主题的变化,但在SplashScreen加
public class PruebaSingleton {
private boolean christmasEvent;
private FirebaseRemoteConfig mFirebaseRemoteConfig;
private static volatile PruebaSingleton _instance;
private PruebaSingleton(){
fetchRemoteConfig();
}
public synchronized static PruebaSingleton getInstance(){
if(_instance == null){
synchronized (PruebaSingleton.class) {
if (_instance == null) _instance = new PruebaSingleton();
}
}
return _instance;
}
private void fetchRemoteConfig() {
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
mFirebaseRemoteConfig.setConfigSettings(
new FirebaseRemoteConfigSettings.Builder().setDeveloperModeEnabled(BuildConfig.DEBUG)
.build());
mFirebaseRemoteConfig.fetch(0).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
mFirebaseRemoteConfig.activateFetched();
}
christmasEvent = mFirebaseRemoteConfig.getBoolean("christmas_ottaa_mode");
}).addOnFailureListener(e -> {
});
}
public boolean isChristmasModeEnabled(){
return christmasEvent;
}
现在,在这之后,我只需实例化一次这个单例来获取远程配置的数据,并影响我的整个应用程序
在mySplashScreen onCreate()上
然后我用这种方法在我所有的活动中得到布尔值
PruebaSingleton.getInstance().isChristmasModeEnabled();
这样我就可以改变主题了
问题是,有时候(通常不是,但在大约10次启动中发生了2次),在启动屏幕发送到第一个活动后,从我的启动屏幕内的单例获取数据,这会导致我的第一个活动没有显示主题,但我的其他活动会显示主题
我的问题是
当我在SplashScreen中时,是否还有其他方法来处理抓取
考虑制作一个界面会使我的SplashScreen慢一点,直到在singleton类中完成所有的获取工作,但是我也不想在第一个活动中显示任何弹出对话框来告诉用户正在等待获取
这更像是一个性能问题,因为在抓取完成时,splashscreen需要快速进入第一个活动,而不是等待更多的时间来获取数据,因为如果发生这种情况,我将降低尝试加载圣诞主题的应用程序的性能
此外,第一次提取应能正常工作,第二次启动将加载第一次提取的数据,然后等待12小时请求新数据,因此,我需要在第一时间将所有fetch值设置为true的活动都设置为true。您的单例需要公开一种方法,让其他代码附加一个侦听器,以了解何时完成提取,类似于将侦听器附加到执行提取的任务的方式。或者,您可以只公开任务本身
我所指的任务由以下命令返回:
mFirebaseRemoteConfig.fetch(0)
您的单例需要公开一种方法,让其他一些代码附加侦听器,以了解提取何时完成,类似于将侦听器附加到执行提取的任务的方式。或者,您可以只公开任务本身
我所指的任务由以下命令返回:
mFirebaseRemoteConfig.fetch(0)
我通过一个简单的回调解决了这个问题,正如Doug所说,下面是我所做的以及它是如何工作的
首先,我创建了一个接口,该接口将在获取值为true或false时调用:
public interface SingletonListener {
void onRemoteFetch(boolean isFetched);
}
然后在我的singleton中,当我知道已获取接口时,我只填充接口的值,如果发生错误,我只将其设置为false:
mFirebaseRemoteConfig.fetch(0).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
mFirebaseRemoteConfig.activateFetched();
}
christmasEvent = mFirebaseRemoteConfig.getBoolean("christmas_ottaa_mode");
mSingletonListener.onRemoteFetch(christmasEvent);
}).addOnFailureListener(e -> {
mSingletonListener.onRemoteFetch(false);
});
//Setters and getters, so in Splash, when I know it's fetched I just set the value to the Singleton and then just get it everywhere in the app
public boolean isChristmasMode() {
return christmasMode;
}
public void setChristmasMode(boolean christmasMode) {
this.christmasMode = christmasMode;
}
以及该接口的实现集:
public void setInterfaz(SingletonListener listener){
this.mSingletonListener = listener;
}
然后在我的SplashScreen中,我只需等待该值被提取到仪表板,因为这是一个加载屏幕,我并不真正关心再等待1或2秒:
初始化单例并附加接口
RemoteConfigSingleton.getInstance().setInterfaz(this);
然后实现该方法并等待结果访问仪表板:
@Override
public void onRemoteFetch(boolean isFetched) {
accessDashboard();
RemoteConfigSingleton.getInstance().setChristmasMode(isFetched);
}
由于我不关心取数的值,无论是真是假,我都会在知道数据已被取数后访问仪表板,如果数据已完成或发生错误
例如,在任何需要更改某个主题的活动中,我只调用christmasEvent返回的布尔值,现在我知道它有一些值:
if(RemoteConfigSingleton.getInstance().isChristmasMode()){
toolbar.setBackgroundResource(R.color.christmas);
Christmas stuff...
}
}
我通过一个简单的回调解决了这个问题,正如Doug所说,下面是我所做的以及它是如何工作的
首先,我创建了一个接口,该接口将在获取值为true或false时调用:
public interface SingletonListener {
void onRemoteFetch(boolean isFetched);
}
然后在我的singleton中,当我知道已获取接口时,我只填充接口的值,如果发生错误,我只将其设置为false:
mFirebaseRemoteConfig.fetch(0).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
mFirebaseRemoteConfig.activateFetched();
}
christmasEvent = mFirebaseRemoteConfig.getBoolean("christmas_ottaa_mode");
mSingletonListener.onRemoteFetch(christmasEvent);
}).addOnFailureListener(e -> {
mSingletonListener.onRemoteFetch(false);
});
//Setters and getters, so in Splash, when I know it's fetched I just set the value to the Singleton and then just get it everywhere in the app
public boolean isChristmasMode() {
return christmasMode;
}
public void setChristmasMode(boolean christmasMode) {
this.christmasMode = christmasMode;
}
以及该接口的实现集:
public void setInterfaz(SingletonListener listener){
this.mSingletonListener = listener;
}
然后在我的SplashScreen中,我只需等待该值被提取到仪表板,因为这是一个加载屏幕,我并不真正关心再等待1或2秒:
初始化单例并附加接口
RemoteConfigSingleton.getInstance().setInterfaz(this);
然后实现该方法并等待结果访问仪表板:
@Override
public void onRemoteFetch(boolean isFetched) {
accessDashboard();
RemoteConfigSingleton.getInstance().setChristmasMode(isFetched);
}
由于我不关心取数的值,无论是真是假,我都会在知道数据已被取数后访问仪表板,如果数据已完成或发生错误
例如,在任何需要更改某个主题的活动中,我只调用christmasEvent返回的布尔值,现在我知道它有一些值:
if(RemoteConfigSingleton.getInstance().isChristmasMode()){
toolbar.setBackgroundResource(R.color.christmas);
Christmas stuff...
}
}
谢谢道格,我会试试的!谢谢道格,我会试试的!