我正在使用Dagger 2
处理MVP结构我可以与Activity
& Fragment
通过属性注入来获取演示者的实例BaseTopPresenter
。
我的问题是我需要将我的演示者BaseTopPresenter presenter;
注入服务FirebaseMsgService
而不在活动中获取静态方法getComponent()
以获取组件并调用inject()
获得演示者BaseTopPresenter
。
p / s:我考虑过使用LocalBroadcastReceiver
从Service
进行UI更新,但我正在尝试做MVP。请帮助我提供一种优雅的方式来获取Service
内部的演示者实例,因为我有很多用例。
在MainApplication.java中:
public class MainApplication extends Application {
/**
* Dagger 2
*/
private AppComponent appComponent;
public static AppComponent getAppComponent(Context context) {
return ((MainApplication) context.getApplicationContext()).appComponent;
}
@Override
public void onCreate() {
super.onCreate();
// Dagger 2
appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.networkModule(new NetworkModule(getString(R.string.base_url)))
.build();
}
}
在FirebaseMsgService.java中:
@ActivityScope
public class FirebaseMsgService extends FirebaseMessagingService {
@Inject
BaseTopPresenter presenter;
@Inject
PreferenceStore preferences;
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
// Dagger 2 : ACTUALLY I DON'T WANT USE THIS STATIC METHOD ANYMORE
// I'M TRYING TO FIND THE OTHER WAY TO GET EXISTED PRESENTER VIA @INJECT HERE
BaseActivity.getAsukabuComponent().inject(this);
if (remoteMessage != null) sendNotification(remoteMessage);
}
private void sendNotification(RemoteMessage remoteMessage) {
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
// PRESENTER AS PARAMETER
CustomizeNotification customizeNotification =
new CustomizeNotification(this, presenter, remoteMessage);
notificationManager.notify(customizeNotification.getNotifyType(), customizeNotification.build());
}
}
在CustomizeNotifications.java中:
public class CustomizeNotification extends NotificationCompat.Builder {
private BaseTopPresenter presenter;
// Data
private static final int NEW_FOLLOWER = 1;
private static final String KEY_IS_FOLLOWER = "is_follower";
private static final String KEY_NOTIFICATION_MESSAGE = "notification_message";
private static final String KEY_EXTRA_NOTIFICATION_DATA = "KEY_EXTRA_NOTIFICATION_DATA";
private int notifyType = 0;
private RemoteMessage remoteMessage;
// The others
private Context context;
public CustomizeNotification(Context context, BaseTopPresenter presenter, RemoteMessage remoteMessage) {
super(context);
this.presenter = presenter;
this.context = context;
this.remoteMessage = remoteMessage;
// Inject dagger 2
Map<String, String> map = remoteMessage.getData();
Bundle mBundle = new Bundle();
for (Map.Entry<String, String> entry : map.entrySet())
mBundle.putString(entry.getKey(), entry.getValue());
Intent intent = new Intent(context, StockActivity.class);
intent.putExtra(KEY_EXTRA_NOTIFICATION_DATA, mBundle);
notifyType = Integer.valueOf(mBundle.getString(KEY_NOTIFY_TYPE));
switch (notifyType) {
case NEW_FOLLOWER:
if (remoteMessage.getNotification().getBody() != null)
implementFollower(intent, mBundle, remoteMessage.getNotification().getBody());
break;
}
}
private void implementFollower(Intent intent, Bundle mBundle, String body) {
// Show dialog only
runInForeground(mBundle);
}
private void runInForeground(Bundle mBundle) {
// Handler
Handler handler = new Handler(Looper.getMainLooper());
// Foreground : I NEED UPDATE EXISTED DATA ON UI IN HERE
handler.post(() -> {
presenter.updateNotification(mBundle);
});
}
}
在BaseTopPresenter.java中:
@ActivityScope
public class BaseTopPresenter extends BasePresenter {
@Inject
public BaseTopPresenter(AsukabuApi asukabuApi, PreferenceStore preferenceStore) {
super(asukabuApi, preferenceStore);
}
public void updateNotification(Bundle mBundle) {
if (notificationView != null) notificationView.onUpdateNotifications(mBundle);
}
}
在BaseTopActivity.java中:
@ActivityScope
public abstract class BaseTopActivity extends BaseActivity implements BaseTopView, BaseTopView.NotificationView {
@Inject
BaseTopPresenter baseTopPresenter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Dagger2
*/
getAsukabuComponent().inject(this);
}
@Override
public void onUpdateNotifications(Bundle mBundle) {
// Handle notifications
// show dialog
if (dialog != null) dialog.dismiss();
dialog = CustomDialog.getInstance(
mBundle.getString(KEY_NOTIFICATION_MESSAGE),
new CustomDialog.DialogButton(getString(R.string.OK),
(dialog1, which) -> {
}), new CustomDialog.DialogButton(getString(R.string.cancel),
(dialog12, which) -> dialog12.dismiss()));
// show
dialog.show(getSupportFragmentManager());
break;
}
}
}
在BaseActivity.java中:
@ActivityScope
public abstract class BaseActivity extends AppCompatActivity implements BaseView {
// I DON'T WANT USE THIS STATIC VAR ANYMORE, TRYING TO GET THIS EXIST COMPONENT IN SERVICE WITHOUT CREATE INSTANCE AGAIN
private static Component Component;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Dagger 2
Component = DaggerComponent.builder()
.appComponent(MainApplication.getAppComponent(this)).build();
}
public static Component getComponent() {
return Component;
}
}
在Component.java中:
@ActivityScope
@Component(dependencies = {AppComponent.class})
public interface Component {
// Services
void inject(FirebaseIDService service);
void inject(FirebaseMsgService service);
}
在AppComponent.java中:
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
// Get FCM API
FCMApi getFCMApi();
// Get Shared Pref.
PreferenceStore getPreferenceStore();
Context context();
}
在AppModule.java中:
@Module
public class AppModule {
private Application mApplication;
public AppModule(Application application) {
mApplication = application;
}
@Singleton
@Provides
Context provideContext() {
return mApplication.getApplicationContext();
}
@Provides
@Singleton
Application providesApplication() {
return mApplication;
}
@Singleton
@Provides
SharedPreferences provideSharedPreferences(Context context) {
return context.getSharedPreferences(PREF, Context.MODE_PRIVATE);
}
@Singleton
@Provides
SharedPreferences.Editor provideSharedPreferencesEditor(SharedPreferences sharedPreferences) {
return sharedPreferences.edit();
}
}
更新:在尝试了Alex的回答之后。这不适合我的情况。
实际上,我的情况:
我想在Component
中获取BaseActivity
个对象。人们有另一个想法吗?
答案 0 :(得分:0)
您可以将组件存储在<!DOCTYPE html>
<html lang="en">
<head>
<title>TASKS</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body ng-app="app">
<div ng-controller="sampleController">
<h3>To do</h3>
<table class="table table-striped table-hover col-sm-4">
<thead>
<tr>
<th>Task</th>
<th>Time</th>
<th>Done</th>
</tr>
</thead>
<tbody ng-repeat="x in firstTable">
<tr>
<td>x.taskName</td>
<td> x.tastTime</td>
<td><input type="checkbox" ng-click="moveData($index)"/></td>
</tr>
</tbody>
</table>
<h3>Done</h3>
<table class="table table-striped table-hover col-sm-4">
<thead>
<tr>
<th>Task</th>
<th>Time</th>
<th>Done</th>
</tr>
</thead>
<tbody ng-repeat="x in secondTable">
<tr>
<td>x.taskName</td>
<td> x.tastTime</td>
<td><input type="checkbox" /></td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
var app=angular.module("app",[]);
app.controller("sampleController",["$scope",function($scope){
$scope.firstTable=[{taskName:'Task_One',tastTime:'5 min'},{taskName:'Task_Two',tastTime:'2 min'},{taskName:'Task_Three',tastTime:'2 min'}];
$scope.secondTable=[];
$scope.moveData=function(index){
$scope.secondTable.push($scope.firstTable[index]);
$scope.firstTable.splice(index,1);
};
}]);
</script>
</html>
中,并使用接口和转换访问它:
示例:
Application
在您的服务中,获取应用程序上下文并将其转发到该界面,如下所示:
public interface HasComponent<T> {
T getComponent();
}
public class MainApplication extends Application implements HasComponent<AppComponent> {
//your code, then
@Override
public AppComponent getComponent() {
return this.appComponent;
}
}