分离 Activity 和 GoogleApiClient 的关注点

Posted

技术标签:

【中文标题】分离 Activity 和 GoogleApiClient 的关注点【英文标题】:Separating the Concerns of Activity and GoogleApiClient 【发布时间】:2015-10-22 10:45:00 【问题描述】:

像往常一样,我的 LoginActivity 中有很多代码,我真的希望将 Activity 职责与 Google Play 登录问题分开。

在多次重写此LoginActivity 代码后,在许多不同的应用程序中,简单(但不那么优雅)的解决方案是将Google API 客户端创建为Application 类对象。但是,由于连接状态会影响 UX 流程,我对这种方法并不满意。

有没有一种优雅的方式将GoogleApiClient 放置在Activity 之外?

【问题讨论】:

【参考方案1】:

0。 TL;DR

对于不耐烦的程序员,可以在GitHub 上找到以下实现的工作版本。

将我们的问题简化为连接概念,我们可以考虑:

    它有有限的状态。 它封装了连接客户端。 它(相当)是独一无二的。 当前状态会影响应用的行为。

1。状态模式

这是一种行为模式,允许对象在其内部状态发生变化时改变其行为。 GoF Design Patterns book 描述了如何用这种模式表示 TCP 连接(这也是我们的例子)。

来自状态机的状态应该是 singleton,而在 Java 中最简单的方法是创建名为 StateEnum,如下所示:

public enum State 
    CREATED 
        void connect(Connection connection) 
            connection.onSignUp();
        
    ,
    OPENING 
        void connect(Connection connection) 
            connection.onSignIn();
        
    ,
    OPENED 
        void disconnect(Connection connection) 
            connection.onSignOut();
        
        void revoke(Connection connection) 
            connection.onRevokeAndSignOut();
        
    ,
    CLOSED 
        void connect(Connection connection) 
            connection.onSignIn();
        
    ;

    void connect(Connection connection) 
    void disconnect(Connection connection) 
    void revoke(Connection connection) 

Activity 将通过connect()disconnect()revoke() 方法与Connection 抽象类(保存上下文)进行通信。当前状态定义了这些方法的行为方式:

public void connect() 
    currentState.connect(this);


public void disconnect() 
    currentState.disconnect(this);


public void revoke() 
    currentState.revoke(this);


private void changeState(State state) 
    currentState = state;
    setChanged();
    notifyObservers(state);

2。代理模式

GoogleConnection类继承自Connection并封装了GoogleApiClient,所以必须同时提供ConnectionCallbacksOnConnectionFailedListener,如下:

@Override
public void onConnected(Bundle connectionHint) 
    changeState(State.OPENED);


@Override
public void onConnectionSuspended(int cause) 
    mGoogleApiClient.connect();


@Override
public void onConnectionFailed(ConnectionResult result) 
    if (state.equals(State.CLOSED) && result.hasResolution()) 
        changeState(State.CREATED);
        connectionResult = result;
     else 
        connect();
    


public void onActivityResult(int resultCode) 
    if (resultCode == Activity.RESULT_OK) 
        connect();
     else 
        changeState(State.CREATED);
    

本说明第二步需要onSignIn()onSignUp()onSignOut()onRevokeAndSignOut方法。

public void onSignUp() 
    try 
        Activity activity = activityWeakReference.get();
        changeState(State.OPENING);
        connectionResult.startResolutionForResult(activity, REQUEST_CODE);
     catch (IntentSender.SendIntentException e) 
        changeState(State.CREATED);
        mGoogleApiClient.connect();
    


public void onSignIn() 
    if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) 
        mGoogleApiClient.connect();
    


public void onSignOut() 
    Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
    mGoogleApiClient.disconnect();
    changeState(State.CLOSED);
    mGoogleApiClient.connect();


public void onRevokeAndSignOut() 
    Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
    Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient);
    changeState(State.CLOSED);
    mGoogleApiClient = mGoogleApiClientBuilder.build();
    mGoogleApiClient.connect();

3。单例模式

由于不需要重复创建此类,我们将其作为单例提供:

public static Connection getInstance(Activity activity) 
    if (null == sConnection) 
        sConnection = new GoogleConnection(activity);
    

    return sConnection;


public void onActivityResult(int result) 
    if (result == Activity.RESULT_OK) 
        changeState(State.CREATED);
     else 
        changeState(State.CLOSED);
    
    onSignIn();


private GoogleConnection(Activity activity) 
    activityWeakReference = new WeakReference<>(activity);

    googleApiClientBuilder = new GoogleApiClient
           .Builder(activity)
           .addConnectionCallbacks(this)
           .addOnConnectionFailedListener(this)
           .addApi(Plus.API, Plus.PlusOptions.builder().build())
           .addScope(new Scope("email"));

    googleApiClient = googleApiClientBuilder.build();
    currentState = State.CLOSED;

    googleApiClient.connect();

4。可观察模式

Connection 类扩展了 Java Observable,因此一个或多个活动可以观察到状态变化:

@Override
protected void onCreate(Bundle bundle) 
    mConnection = GoogleConnection.getInstance(this);
    mConnection.addObserver(this);


@Override
protected void onDestroy() 
    mConnection.deleteObserver(this);


@Override
protected void onActivityResult(int request, int result, Intent data) 
    if (Connection.REQUEST_CODE == request) 
        mConnection.onActivityResult(result);
    


@Override
public void update(Observable observable, Object data) 
    if (observable == mGoogleConnection) 
        // UI/UX magic happens here ;-)
    

【讨论】:

以上是关于分离 Activity 和 GoogleApiClient 的关注点的主要内容,如果未能解决你的问题,请参考以下文章

Android MVP模式实现组件和业务逻辑分离

Viewmode原理

Android Fragment的特点

Fragment

Android数据流程的优化

北大深研院APP 知识总结: