2016-11-21 9 views
0

Я работаю со структурой MVP с помощью Dagger 2Вводят существующего MVP ведущих от деятельности в службу через Dagger2

Я могу работать очень хорошо с Activity & Fragment путем инъекции собственности, чтобы получить экземпляр ведущих, BaseTopPresenter.

Мой вопроса мне нужно вводить свои ведущий BaseTopPresenter presenter; в службу FirebaseMsgService без получения статического метода getComponent() внутри деятельности, чтобы получить компонент и вызвать inject() получить выступающие BaseTopPresenter.

p/s: Я думал об использовании LocalBroadcastReceiver, чтобы делать обновления пользовательского интерфейса от Service, но я стараюсь делать 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(); 
    } 

} 

UPDATE: После того, как попытался ответить на Алекса. Это неправильно для моего дела.

На самом деле, мой случай:

Я хочу, чтобы получить Component объект в BaseActivity. У людей есть другая идея?

+0

Правильное место для 'inject()' внутри 'Service' является' onCreate() 'не так ли? –

+0

@DavidRawson: Совершенно верно. –

ответ

0

Вы можете хранить компонент в 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; 
    } 
} 

В вашей службе, получить контекст приложения и брось на этот интерфейс, как это:

((HasComponent<AppComponent>) getApplication()).getComponent(); 
+0

Собственно, таким образом работайте с 'MainApplication'. Но в моем случае я хочу получить объект 'Component' в' BaseActivity' (строка 'private static Component Component;'). Я попытался сделать то же самое, но выглядит по-другому. У вас есть другая идея? –