Android С чего начать активность в MVVM Resarlt

#java #android #design-patterns #mvvm #repository-pattern

#java #Android #шаблоны проектирования #mvvm #репозиторий-шаблон

Вопрос:

Я предполагал использовать шаблон MVVM с хранилищем данных. Данные поступили из вызова веб-Api. и на основе полученных данных приложение запускает веб-браузер с возвращенным URL.

  1. при взаимодействии с пользователем действие вызывает ViewModel, которому принадлежат данные:

CheckOutActivity.java:

 MaterialRippleLayout makeOrder = findViewById(R.id.btn_make_order);
    makeOrder.setOnClickListener(view ->{
        viewModel.makeOrder();
    });
  
  1. ViewModel вызывает DataRepository с соответствующими данными (optionalShippingEntityIds) для асинхронного вызова веб-Api:

CheckOutViewModel.java

 public void makeOrder(){
    cartRepository.makeOrder(optionalShippingEntityIds.getValue());
}
  

Репозиторий был создан ранее:

 public CheckOutViewModel(@NonNull Application application) {
    super(application);
    cartRepository = new CartRepository(application);
}  
  
  1. в DataRepository выполняется вызов Api:

Расположение карт

 public void makeOrder(ArrayList<Integer> optionalShippingEntityIds){
    HashMap<String,String> map = new HashMap<String,String>();
    String  idsString=optionalShippingEntityIds.toString();
    map.put("shipment_saleitem_id",idsString);
    rest.httpRequest(RestAdapter.HttpVerb.POST,"order",map,new makeOrderHandler());
}
  

Конструктор CartRepository:

 private RestAdapter rest;
private Context context;

public CartRepository(Context context) {
    this.context = context;
    rest = RestAdapter.getInstance(context);
    version.setValue(0);
}
  

4.HttpResponseHandler Обрабатывает URL-адрес открытия веб-браузера или всплывающее сообщение об ошибке

CartRepository.java

 class makeOrderHandler extends JsonHttpResponseHandler{
    @Override
    public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
        if(statusCode == 200){
            try {
                Toast.makeText(context,"order number " response.getInt("order_id") "has been created",Toast.LENGTH_SHORT).show();
                String redirectUrl = response.getString("init_payment_url");
                version.setValue(version.getValue()  1);

                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(redirectUrl));
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        context.startActivity(intent);
                        ((Activity)context).finishAffinity();
                        //System.exit(0);

                        /*Intent chooserIntent = Intent.createChooser(intent, "Open With");
                        chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(chooserIntent);*/
                    }
                }, 2000);
            } catch (JSONException e) {
                Toast.makeText(context,"JSON parse error" " : " response.toString(), Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
        }else{
            Log.e("server api changed ", "error in getting response using known api n"   response.toString());
            Toast.makeText(context,"api change",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, String res, Throwable t) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
        Log.e("server 500", "error in getting response using async-apache-http call" " : " res);
        t.printStackTrace();
        Toast.makeText(context, "خطا سرور ", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, Throwable t, JSONObject e) {
        if(statusCode == 504){
            Toast.makeText(context,"The Order hasnt been created duo to internal problem. please try again",Toast.LENGTH_SHORT).show();
        }else{
            Log.e("server api changed", "error in getting response using known api n"   e.toString());
            t.printStackTrace();
            Toast.makeText(context,"Api is unknown",Toast.LENGTH_SHORT).show();
        }
    }
}
  

Проблема в том, что после запуска приложения на некоторых устройствах в строке ((Activity)context).finishAffinity(); происходит сбой приложения, потому что context это экземпляр контекста приложения, а не экземпляр контекста действия.

  • если я передам экземпляр Activity через ViewModel, я только что нарушил MVVM.
  • если я создам интерфейс в Activity и реализую его. это нарушает ответственность за одно действие (обработчик ответа хранилища данных должен обрабатывать startActivity)
    поэтому я не знаю, как справиться с этим идеально.
  • если я исключу ViewModel makeOrder и создам репозиторий с контекстом действия, я думаю, что его ViewModel отвечает за обработку задания по обработке данных.

….

Итак, я смущен правильным решением для обработки startActivity и Toast в ответ.

если бы кто-нибудь мог помочь мне с правильным шаблоном проектирования, я был бы признателен.

Ответ №1:

Ваша viewmodel может расширяться из AndroidViewModel. Из документации: «ViewModel с учетом контекста приложения.

Подклассы должны иметь конструктор, который принимает Application в качестве единственного параметра.»

Комментарии:

1. Спасибо @Toleubek. Я сделал то, что вы сказали. и я передал его в свой репозиторий, но, как я уже говорил ранее. возникает ошибка, поскольку контекст приложения не может запустить действие, только контекст Activit может