#java #android #design-patterns #mvvm #repository-pattern
#java #Android #шаблоны проектирования #mvvm #репозиторий-шаблон
Вопрос:
Я предполагал использовать шаблон MVVM с хранилищем данных. Данные поступили из вызова веб-Api. и на основе полученных данных приложение запускает веб-браузер с возвращенным URL.
- при взаимодействии с пользователем действие вызывает ViewModel, которому принадлежат данные:
CheckOutActivity.java:
MaterialRippleLayout makeOrder = findViewById(R.id.btn_make_order);
makeOrder.setOnClickListener(view ->{
viewModel.makeOrder();
});
- ViewModel вызывает DataRepository с соответствующими данными (optionalShippingEntityIds) для асинхронного вызова веб-Api:
CheckOutViewModel.java
public void makeOrder(){
cartRepository.makeOrder(optionalShippingEntityIds.getValue());
}
Репозиторий был создан ранее:
public CheckOutViewModel(@NonNull Application application) {
super(application);
cartRepository = new CartRepository(application);
}
- в 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 может