分离Activity和GoogleApiClient的关注点 [英] Separating the Concerns of Activity and GoogleApiClient

查看:17
本文介绍了分离Activity和GoogleApiClient的关注点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As usual there is a lot of code in my LoginActivity and I really would prefer to separate the Activity responsibilities from the Google Play sign in concerns.

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

After rewriting this LoginActivity code several times, in many different apps, the easy (and not so elegant) solution was create the Google API client as a Application class object. But, since the connection state affect the UX flow, I never was happy about with this approach.

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

Is there an elegant way of place the GoogleApiClient outside the Activity?

推荐答案

0.TL;博士

对于不耐烦的编码器,可以在 GitHub.

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

Reducing our problem only to the connection concept, we may consider that:

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

1.状态模式

这是一种行为模式,允许对象在其内部状态发生变化时改变其行为.GoF 设计模式书籍 描述了 TCP 连接如何由这种模式表示(这也是我们的情况).

1. State Pattern

This is a behavioral pattern the allow an object to alter its behavior when its internal state changes. The GoF Design Patterns book describes how a TCP connection can be represent by this pattern (which is also our case).

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

A state from a state machine should be a singleton, and the easiest away of doing it in Java was to create Enum named State as follows:

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 与 Connection 抽象类(保存上下文)通信()revoke().当前状态定义了这些方法的行为方式:

The Activity will communicate with the Connection abstract class (which holds the context) through the methods connect(), disconnect(), and revoke(). The current state defines how these methods will behave:

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,所以必须同时提供ConnectionCallbacks和<代码>OnConnectionFailedListener如下:

2. Proxy Pattern

The class GoogleConnection inherits from Connection and encapsulates the GoogleApiClient, so it must provide both ConnectionCallbacks and OnConnectionFailedListener as follows:

@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 是必需的这个解释的第二步.

The methods onSignIn(), onSignUp(), onSignOut(), and onRevokeAndSignOut are required on the second step of this explanation.

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.单例模式

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

3. Singleton Pattern

Since there is not need to recreate this class repeatedly, we provide it as a singleton:

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,因此一个或多个 Activity 可以观察状态变化:

4. Observable Pattern

The Connection class extends Java Observable, so one or many activities can observe the state changes:

@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的关注点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆