Выполнить функцию в текущем действии после onReponse () Retrofit себя вне службы - PullRequest
2 голосов
/ 07 марта 2020

В настоящее время я работаю над приложением Android, и у меня проблема с обработкой запроса и выполнением функции сразу после. Дело в том, что мой запрос на модификацию находится в контроллере, используемом службой, и я вызываю функцию службы внутри своей активности (понятно?). Ясно, что мне нужно управлять одним пользователем (получить и обновить sh токен доступа из веб-сервиса), и мне нужно иметь возможность вызывать функцию refreshToken () и выполнять некоторый код после получения и анализа ответа.

Это мой код:

UserActivity

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 обрабатывать свой ответ и только после выполнения другой функции внутри моего пользовательского интерфейса? Или внутри моей функцииenerateByRefreshToken ()?

Спасибо!

1 Ответ

2 голосов
/ 10 марта 2020

Есть ли у вас какие-либо идеи о том, как заставить мою функцию RefroFit обрабатывать свой ответ и только после выполнения другой функции внутри моего пользовательского интерфейса? Или внутри моей функцииenerateByRefreshToken ()?

В соответствии с текущей реализацией, Вы можете добиться этого, используя Callbacks. Создайте два обратных вызова для

  1. Получите внутреннюю службу usertemp от контроллера после успешного выполнения.

  2. Второй обратный вызов для отправки user Возврат к активности из службы

Итак, выполните следующие шаги:

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) Передача объекта обратного вызова из действия в службу и реализация вызова метода обновлений пользовательского интерфейса

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

, но вы не инициализируете user объект в UserActivity, ни добавление его в mIntent объект, так что вам нужно user объект с token и другими необходимыми свойствами в деятельности для сетевых вызовов.

Вы можете оптимизировать поток с лямбдами, Rx java et c как w флигель.

...