分离 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 中最简单的方法是创建名为 State
的 Enum
,如下所示:
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
,所以必须同时提供ConnectionCallbacks
和OnConnectionFailedListener
,如下:
@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 的关注点的主要内容,如果未能解决你的问题,请参考以下文章