在服务外的 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 实现此目的。创建两个回调

  1. 执行成功后从控制器获取usertemp内部服务

  2. 第二次回调将 user 对象从服务

  3. 发送回 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 等优化流程。