分离Activity和GoogleApiClient的关注点 [英] Separating the Concerns of Activity and 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.状态模式
这是一种行为模式,允许对象在其内部状态发生变化时改变其行为.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中最简单的方法是创建名为State
的Enum
如下:
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屋!