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

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

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

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

【问题讨论】:

    标签: android design-patterns google-plus google-play-services google-api-client


    【解决方案1】:

    0。 TL;DR

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

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

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

    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 ;-)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 2014-02-09
      • 2013-03-28
      • 2011-01-06
      • 1970-01-01
      相关资源
      最近更新 更多