在服务外的 Retrofit 本身的 onReponse() 之后执行当前 activity 中的函数
Execute function in current activity after onReponse() of Retrofit itself outside a service
我目前正在开发一个 Android 应用程序,但我在处理请求和紧接着执行函数时遇到了问题。
事实上,我的 Retrofit 请求在一个控制器中,由一个服务使用,我正在我的 Activity 中调用服务函数(我清楚吗?)。
显然,我必须管理一个用户(从 Web 服务获取和刷新访问令牌)并且我需要能够调用我的 refreshToken() 函数并在获取和解析响应后执行一些代码。
这是我的代码:
用户Activity
public class UserActivity extends AppCompatActivity {
private final static String TAG = "UserActivity";
private User user;
private TextView textViewAccessTokenShow, textViewExpiresInShow, textViewIGPShow, textViewRefreshTokenShow;
private LoginController loginController;
private Wso2Service wso2Service, wso2ServiceIS;
boolean mBounded;
private LoginService loginService;
private Intent mIntent;
//Connection to LoginService
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(UserActivity.this, "Service is disconnected", Toast.LENGTH_LONG).show();
mBounded = false;
loginService = null;
Log.e(TAG, "onServiceDisconnected: " );
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(UserActivity.this, "Service is connected", Toast.LENGTH_LONG).show();
mBounded = true;
LoginService.LocalBinder mLocalBinder = (LoginService.LocalBinder) service;
loginService = mLocalBinder.getServerInstance();
user = loginService.getUser();
refreshIHM();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
mIntent = new Intent(this, LoginService.class);
textViewAccessTokenShow = findViewById(R.id.textViewAccessTokenShow);
textViewRefreshTokenShow = findViewById(R.id.textViewRefreshTokenShow);
textViewExpiresInShow = findViewById(R.id.textViewExpiresInShow);
textViewIGPShow = findViewById(R.id.textViewIGPShow);
}
@Override
protected void onResume() { //Getting my user updated outside this activity and printing his informations
super.onResume();
Log.i(TAG, "onResume: ");
if(mBounded == false){
bindService(mIntent, mConnection, BIND_AUTO_CREATE);
} else {
user = loginService.getUser();
refreshIHM();
}
}
public void onClickRefreshToken(View view){
//Where i have to refresh my token, and after that executing refreshIHM()
refreshIHM();
}
public void refreshIHM(){
Log.d(TAG, "refreshIHM() called");
Log.i(TAG, "refreshIHM: "+user.toString());
textViewExpiresInShow.setVisibility(View.VISIBLE);
textViewAccessTokenShow.setVisibility(View.VISIBLE);
textViewRefreshTokenShow.setVisibility(View.VISIBLE);
textViewIGPShow.setVisibility(View.VISIBLE);
textViewAccessTokenShow.setText(user.getAccess_token());
textViewAccessTokenShow.invalidate();
textViewAccessTokenShow.requestLayout();
textViewRefreshTokenShow.setText(user.getRefresh_token());
textViewRefreshTokenShow.invalidate();
textViewRefreshTokenShow.requestLayout();
textViewExpiresInShow.setText(String.valueOf(user.getExpire_in()));
textViewExpiresInShow.invalidate();
textViewExpiresInShow.requestLayout();
textViewIGPShow.setText(user.getId_group_parent());
textViewIGPShow.invalidate();
textViewIGPShow.requestLayout();
}
}
LoginController,我在其中执行有关用户数据的所有功能
public class LoginController {
public static final String TAG = "LOGINSERVICE";
private User usertemp;
private Wso2Service wso2Service, wso2ServiceIS;
public LoginController(){
this.wso2Service = new Retrofit.Builder()
.baseUrl(Wso2Service.APIMENDPOINT)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(Wso2Service.class);
this.wso2ServiceIS = new Retrofit.Builder()
.baseUrl(Wso2Service.ISENDPOINT)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(Wso2Service.class);
}
public User parseUserInfo(String request, User user) {
try {
JSONObject jo = new JSONObject(request);
user.setAccess_token(jo.getString("access_token"));
user.setRefresh_token(jo.getString("refresh_token"));
user.setScope(jo.getString("scope"));
user.setId_token(jo.getString("id_token"));
user.setToken_type(jo.getString("token_type"));
user.setExpire_in(jo.getInt("expires_in"));
return user;
} catch (Exception e){
Log.e(TAG, "getUserInfo: "+e.toString());
}
return null;
}
public User parseIdGroupParentInfo(String request, User user){
try {
Log.i(TAG, "parseIdGroupParentInfo: "+request);
JSONObject jo = new JSONObject(request);
user.setId_group_parent(jo.getString("id_group_parent"));
return user;
} catch (Exception e){
Log.e(TAG, "parseIdGroupParentInfo: "+e.toString());
}
return null;
}
public void refreshToken(User user){
this.usertemp = user;
Log.i(TAG, "refreshToken: ");
this.wso2Service.getTokensByRefresh("refresh_token",user.getRefresh_token(),"openid", ApiConstants.token).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) {
//On parse la réponse
usertemp.setLogin_request_responseJSON(response.body());
parseUserInfo(response.body(), usertemp);
Log.i(TAG, "onLoginReady: " + usertemp.toString());
wso2ServiceIS.getUserInfo("Bearer "+usertemp.getAccess_token()).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(TAG, "onResponse: "+response.code()+response.body());
usertemp = parseIdGroupParentInfo(response.body(),usertemp);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
} else {
Log.e(TAG, "onResponse: " );
Log.e(TAG, "onResponse: Code "+response.code()+" Body : "+response.body() );
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
}
}
LoginService,我在每次活动中调用的每次都使用相同的用户
public class LoginService extends Service {
public final String TAG = "LoginService";
private User user;
private LoginController loginController;
IBinder mBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class LocalBinder extends Binder {
public LoginService getServerInstance() {
return LoginService.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
this.user = (User)intent.getSerializableExtra("user");
Log.i(TAG, "onStartCommand: "+user.toString());
loginController = new LoginController();
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
public User getUser(){
Log.i(TAG, "getUser: ");
return this.user;
}
public void regenerateByRefreshToken(){
Log.d(TAG, "regenerateByRefreshToken: ");
loginController.refreshToken(user);
Log.d(TAG, "regenerateByRefreshToken: end");
}
}
您是否知道如何让我的 RefroFit 函数处理它的响应,并且仅在我的 UI 中执行另一个函数之后?或者在我的 regenerateByRefreshToken() 函数中?
谢谢!
Do you have any idea about how to make my RefroFit function handle its
response and only after executing another function inside my UI ? Or
inside my regenerateByRefreshToken() function ?
根据当前的实施,您可以使用 Callbacks
实现此目的。创建两个回调
执行成功后从控制器获取usertemp
内部服务
第二次回调将 user
对象从服务
发送回 activity
所以请按照以下步骤操作:
a) 创建回调接口
// create new OnUserRefresh.java
public interface OnUserRefresh{
void onRefresh(User user);
void onError(Throwable t);
}
b) 修改控制器接收回调参考
public class LoginController {
// code...
public void refreshToken(User user, OnUserRefresh onUserRefresh){
this.usertemp = user;
Log.i(TAG, "refreshToken: ");
this.wso2Service.getTokensByRefresh("refresh_token",user.getRefresh_token(),"openid", ApiConstants.token).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) {
//On parse la réponse
usertemp.setLogin_request_responseJSON(response.body());
parseUserInfo(response.body(), usertemp);
Log.i(TAG, "onLoginReady: " + usertemp.toString());
wso2ServiceIS.getUserInfo("Bearer "+usertemp.getAccess_token()).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(TAG, "onResponse: "+response.code()+response.body());
usertemp = parseIdGroupParentInfo(response.body(),usertemp);
onUserRefresh.onRefresh(usertemp);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
onUserRefresh.onError(t);
}
});
} else {
Log.e(TAG, "onResponse: " );
Log.e(TAG, "onResponse: Code "+response.code()+" Body : "+response.body() );
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
}
}
c) 将回调对象从服务传递到控制器
public class LoginService extends Service {
/*Add interface, to be used for data passing*/
public void regenerateByRefreshToken(OnUserRefresh onUserRefresh){
Log.d(TAG, "regenerateByRefreshToken: ");
loginController.refreshToken(user, new OnUserRefresh(){
@Override
void onRefresh(User user){
this.user = user;
onUserRefresh.onRefresh(user); // trigger onRefresh in client i.e. activity
}
@Override
void onError(Throwable t){
onUserRefresh.onError(t);
// log error etc
}
});
Log.d(TAG, "regenerateByRefreshToken: end");
}
}
d) 将回调对象从 activity 传递给服务并实现 UI 更新方法调用
public class UserActivity extends AppCompatActivity {
public void onClickRefreshToken(View view){
//Where i have to refresh my token, and after that executing refreshIHM()
loginService.regenerateByRefreshToken(new OnUserRefresh(){
@Override
void onRefresh(User user){
this.user = user;
refreshIHM();
}
@Override
void onError(Throwable t){
// log error etc
}
});
}
}
注意:最初的 user
引用始终是 null
,因为您是从服务中的意图接收到它的
this.user = (User)intent.getSerializableExtra("user");
但是您既没有在 UserActivity
中初始化任何 user
对象,也没有将其添加到 mIntent
对象中,因此您需要一个 user
对象 token
和 activity 中用于网络调用的其他必需属性。
您也可以使用 lambdas、Rxjava 等优化流程。
我目前正在开发一个 Android 应用程序,但我在处理请求和紧接着执行函数时遇到了问题。 事实上,我的 Retrofit 请求在一个控制器中,由一个服务使用,我正在我的 Activity 中调用服务函数(我清楚吗?)。 显然,我必须管理一个用户(从 Web 服务获取和刷新访问令牌)并且我需要能够调用我的 refreshToken() 函数并在获取和解析响应后执行一些代码。
这是我的代码:
用户Activity
public class UserActivity extends AppCompatActivity {
private final static String TAG = "UserActivity";
private User user;
private TextView textViewAccessTokenShow, textViewExpiresInShow, textViewIGPShow, textViewRefreshTokenShow;
private LoginController loginController;
private Wso2Service wso2Service, wso2ServiceIS;
boolean mBounded;
private LoginService loginService;
private Intent mIntent;
//Connection to LoginService
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(UserActivity.this, "Service is disconnected", Toast.LENGTH_LONG).show();
mBounded = false;
loginService = null;
Log.e(TAG, "onServiceDisconnected: " );
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(UserActivity.this, "Service is connected", Toast.LENGTH_LONG).show();
mBounded = true;
LoginService.LocalBinder mLocalBinder = (LoginService.LocalBinder) service;
loginService = mLocalBinder.getServerInstance();
user = loginService.getUser();
refreshIHM();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
mIntent = new Intent(this, LoginService.class);
textViewAccessTokenShow = findViewById(R.id.textViewAccessTokenShow);
textViewRefreshTokenShow = findViewById(R.id.textViewRefreshTokenShow);
textViewExpiresInShow = findViewById(R.id.textViewExpiresInShow);
textViewIGPShow = findViewById(R.id.textViewIGPShow);
}
@Override
protected void onResume() { //Getting my user updated outside this activity and printing his informations
super.onResume();
Log.i(TAG, "onResume: ");
if(mBounded == false){
bindService(mIntent, mConnection, BIND_AUTO_CREATE);
} else {
user = loginService.getUser();
refreshIHM();
}
}
public void onClickRefreshToken(View view){
//Where i have to refresh my token, and after that executing refreshIHM()
refreshIHM();
}
public void refreshIHM(){
Log.d(TAG, "refreshIHM() called");
Log.i(TAG, "refreshIHM: "+user.toString());
textViewExpiresInShow.setVisibility(View.VISIBLE);
textViewAccessTokenShow.setVisibility(View.VISIBLE);
textViewRefreshTokenShow.setVisibility(View.VISIBLE);
textViewIGPShow.setVisibility(View.VISIBLE);
textViewAccessTokenShow.setText(user.getAccess_token());
textViewAccessTokenShow.invalidate();
textViewAccessTokenShow.requestLayout();
textViewRefreshTokenShow.setText(user.getRefresh_token());
textViewRefreshTokenShow.invalidate();
textViewRefreshTokenShow.requestLayout();
textViewExpiresInShow.setText(String.valueOf(user.getExpire_in()));
textViewExpiresInShow.invalidate();
textViewExpiresInShow.requestLayout();
textViewIGPShow.setText(user.getId_group_parent());
textViewIGPShow.invalidate();
textViewIGPShow.requestLayout();
}
}
LoginController,我在其中执行有关用户数据的所有功能
public class LoginController {
public static final String TAG = "LOGINSERVICE";
private User usertemp;
private Wso2Service wso2Service, wso2ServiceIS;
public LoginController(){
this.wso2Service = new Retrofit.Builder()
.baseUrl(Wso2Service.APIMENDPOINT)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(Wso2Service.class);
this.wso2ServiceIS = new Retrofit.Builder()
.baseUrl(Wso2Service.ISENDPOINT)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(Wso2Service.class);
}
public User parseUserInfo(String request, User user) {
try {
JSONObject jo = new JSONObject(request);
user.setAccess_token(jo.getString("access_token"));
user.setRefresh_token(jo.getString("refresh_token"));
user.setScope(jo.getString("scope"));
user.setId_token(jo.getString("id_token"));
user.setToken_type(jo.getString("token_type"));
user.setExpire_in(jo.getInt("expires_in"));
return user;
} catch (Exception e){
Log.e(TAG, "getUserInfo: "+e.toString());
}
return null;
}
public User parseIdGroupParentInfo(String request, User user){
try {
Log.i(TAG, "parseIdGroupParentInfo: "+request);
JSONObject jo = new JSONObject(request);
user.setId_group_parent(jo.getString("id_group_parent"));
return user;
} catch (Exception e){
Log.e(TAG, "parseIdGroupParentInfo: "+e.toString());
}
return null;
}
public void refreshToken(User user){
this.usertemp = user;
Log.i(TAG, "refreshToken: ");
this.wso2Service.getTokensByRefresh("refresh_token",user.getRefresh_token(),"openid", ApiConstants.token).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) {
//On parse la réponse
usertemp.setLogin_request_responseJSON(response.body());
parseUserInfo(response.body(), usertemp);
Log.i(TAG, "onLoginReady: " + usertemp.toString());
wso2ServiceIS.getUserInfo("Bearer "+usertemp.getAccess_token()).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(TAG, "onResponse: "+response.code()+response.body());
usertemp = parseIdGroupParentInfo(response.body(),usertemp);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
} else {
Log.e(TAG, "onResponse: " );
Log.e(TAG, "onResponse: Code "+response.code()+" Body : "+response.body() );
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
}
}
LoginService,我在每次活动中调用的每次都使用相同的用户
public class LoginService extends Service {
public final String TAG = "LoginService";
private User user;
private LoginController loginController;
IBinder mBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class LocalBinder extends Binder {
public LoginService getServerInstance() {
return LoginService.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
this.user = (User)intent.getSerializableExtra("user");
Log.i(TAG, "onStartCommand: "+user.toString());
loginController = new LoginController();
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
public User getUser(){
Log.i(TAG, "getUser: ");
return this.user;
}
public void regenerateByRefreshToken(){
Log.d(TAG, "regenerateByRefreshToken: ");
loginController.refreshToken(user);
Log.d(TAG, "regenerateByRefreshToken: end");
}
}
您是否知道如何让我的 RefroFit 函数处理它的响应,并且仅在我的 UI 中执行另一个函数之后?或者在我的 regenerateByRefreshToken() 函数中?
谢谢!
Do you have any idea about how to make my RefroFit function handle its response and only after executing another function inside my UI ? Or inside my regenerateByRefreshToken() function ?
根据当前的实施,您可以使用 Callbacks
实现此目的。创建两个回调
执行成功后从控制器获取
usertemp
内部服务第二次回调将
user
对象从服务 发送回 activity
所以请按照以下步骤操作:
a) 创建回调接口
// create new OnUserRefresh.java
public interface OnUserRefresh{
void onRefresh(User user);
void onError(Throwable t);
}
b) 修改控制器接收回调参考
public class LoginController {
// code...
public void refreshToken(User user, OnUserRefresh onUserRefresh){
this.usertemp = user;
Log.i(TAG, "refreshToken: ");
this.wso2Service.getTokensByRefresh("refresh_token",user.getRefresh_token(),"openid", ApiConstants.token).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) {
//On parse la réponse
usertemp.setLogin_request_responseJSON(response.body());
parseUserInfo(response.body(), usertemp);
Log.i(TAG, "onLoginReady: " + usertemp.toString());
wso2ServiceIS.getUserInfo("Bearer "+usertemp.getAccess_token()).enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(TAG, "onResponse: "+response.code()+response.body());
usertemp = parseIdGroupParentInfo(response.body(),usertemp);
onUserRefresh.onRefresh(usertemp);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
onUserRefresh.onError(t);
}
});
} else {
Log.e(TAG, "onResponse: " );
Log.e(TAG, "onResponse: Code "+response.code()+" Body : "+response.body() );
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
}
}
c) 将回调对象从服务传递到控制器
public class LoginService extends Service {
/*Add interface, to be used for data passing*/
public void regenerateByRefreshToken(OnUserRefresh onUserRefresh){
Log.d(TAG, "regenerateByRefreshToken: ");
loginController.refreshToken(user, new OnUserRefresh(){
@Override
void onRefresh(User user){
this.user = user;
onUserRefresh.onRefresh(user); // trigger onRefresh in client i.e. activity
}
@Override
void onError(Throwable t){
onUserRefresh.onError(t);
// log error etc
}
});
Log.d(TAG, "regenerateByRefreshToken: end");
}
}
d) 将回调对象从 activity 传递给服务并实现 UI 更新方法调用
public class UserActivity extends AppCompatActivity {
public void onClickRefreshToken(View view){
//Where i have to refresh my token, and after that executing refreshIHM()
loginService.regenerateByRefreshToken(new OnUserRefresh(){
@Override
void onRefresh(User user){
this.user = user;
refreshIHM();
}
@Override
void onError(Throwable t){
// log error etc
}
});
}
}
注意:最初的 user
引用始终是 null
,因为您是从服务中的意图接收到它的
this.user = (User)intent.getSerializableExtra("user");
但是您既没有在 UserActivity
中初始化任何 user
对象,也没有将其添加到 mIntent
对象中,因此您需要一个 user
对象 token
和 activity 中用于网络调用的其他必需属性。
您也可以使用 lambdas、Rxjava 等优化流程。