Merge branch 'tag_architecture_enhancement' into dev

This commit is contained in:
Tariel Hlontsi 2016-04-24 21:02:28 +03:00
commit 3c123f127d
23 changed files with 866 additions and 43 deletions

View File

@ -28,15 +28,15 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.android.support:support-v4:23.3.0'
compile 'com.google.code.gson:gson:2.6.2' compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.1' compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.1' compile 'com.squareup.retrofit2:converter-gson:2.0.1'
compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp:logging-interceptor:2.7.0' compile 'com.squareup.okhttp:logging-interceptor:2.7.0'
compile 'com.android.support:support-v4:23.3.0' compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:appcompat-v7:23.3.0' compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0' compile 'com.android.support:design:23.3.0'
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:cardview-v7:23.3.0' compile 'com.android.support:cardview-v7:23.3.0'
} }

View File

@ -5,44 +5,182 @@ import android.app.Fragment;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import hikapro.com.backpack.model.DetailModel;
import hikapro.com.backpack.model.ItemModel;
import hikapro.com.backpack.model.SetModel;
import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.model.entities.Set; import hikapro.com.backpack.model.entities.Set;
import hikapro.com.backpack.presenter.ItemDetailPresenter;
import hikapro.com.backpack.presenter.ItemListPresenter;
import hikapro.com.backpack.presenter.SetListPresenter;
import hikapro.com.backpack.view.View; import hikapro.com.backpack.view.View;
import hikapro.com.backpack.view.fragments.ItemDetailFragment;
import hikapro.com.backpack.view.fragments.ItemListFragment; import hikapro.com.backpack.view.fragments.ItemListFragment;
import hikapro.com.backpack.view.fragments.SetListFragment; import hikapro.com.backpack.view.fragments.SetListFragment;
public class MainActivity extends Activity implements View.ActivityCallback { public class MainActivity extends Activity implements View.ActivityCallback {
private static String TAG = "TAG";
private FragmentManager fragmentManager; private FragmentManager fragmentManager;
private final StateMaintainer stateMaintainer =
new StateMaintainer(getFragmentManager(), MainActivity.class.getName());
// life cycle -->
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
fragmentManager = getFragmentManager(); fragmentManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(TAG); stateMaintainer.init();
if (fragment == null)
replaceFragment(SetListFragment.construct(), false); if (fragmentManager.getBackStackEntryCount() == 0) {
startSetListFragment();
} else {
Fragment fragment = fragmentManager.findFragmentByTag(SetListFragment.class.getName());
if (fragment != null) {
SetListFragment view = (SetListFragment) fragment;
SetListPresenter presenter = stateMaintainer.get(SetListPresenter.class.getName());
SetModel model = stateMaintainer.get(SetModel.class.getName());
view.setPresenter(presenter);
presenter.setView(view);
presenter.setModel(model);
model.setPresenter(presenter);
}
fragment = fragmentManager.findFragmentByTag(ItemListFragment.class.getName());
if (fragment != null) {
ItemListFragment view = (ItemListFragment) fragment;
ItemListPresenter presenter = stateMaintainer.get(ItemListPresenter.class.getName());
ItemModel model = stateMaintainer.get(ItemModel.class.getName());
view.setPresenter(presenter);
presenter.setView(view);
presenter.setModel(model);
model.setPresenter(presenter);
}
fragment = fragmentManager.findFragmentByTag(ItemDetailFragment.class.getName());
if (fragment != null) {
ItemDetailFragment view = (ItemDetailFragment) fragment;
ItemDetailPresenter presenter = stateMaintainer.get(ItemDetailPresenter.class.getName());
DetailModel model = stateMaintainer.get(DetailModel.class.getName());
view.setPresenter(presenter);
presenter.setView(view);
presenter.setModel(model);
model.setPresenter(presenter);
}
}
Log.i("On create", "Activity");
}
@Override
protected void onStart() {
super.onStart();
Log.i("onStart", "Activity");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i("onRestart", "Activity");
}
@Override
protected void onResume() {
super.onResume();
Log.i("onResume", "Activity");
}
@Override
protected void onPause() {
super.onPause();
Log.i("onPause", "Activity");
}
@Override
protected void onStop() {
super.onStop();
Log.i("onStop", "Activity");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i("onDestroy", "Activity");
}
// life cycle <--
@Override
public void startSetListFragment() {
SetListFragment view = SetListFragment.construct();
SetListPresenter presenter = new SetListPresenter();
SetModel model = new SetModel();
view.setPresenter(presenter);
presenter.setView(view);
presenter.setModel(model);
model.setPresenter(presenter);
replaceFragment(view, true, SetListFragment.class.getName());
stateMaintainer.put(presenter);
stateMaintainer.put(model);
} }
@Override @Override
public void startItemListFragment(Set set) { public void startItemListFragment(Set set) {
replaceFragment(ItemListFragment.newFromSet(set), true);
ItemListFragment view = ItemListFragment.newFromSet(set);
ItemListPresenter presenter = new ItemListPresenter();
ItemModel model = new ItemModel();
view.setPresenter(presenter);
presenter.setView(view);
presenter.setModel(model);
model.setPresenter(presenter);
replaceFragment(view, true, ItemListFragment.class.getName());
stateMaintainer.put(presenter);
stateMaintainer.put(model);
} }
@Override @Override
public void startItemDetailFragment() { public void startItemDetailFragment(Item item) {
ItemDetailFragment view = ItemDetailFragment.newFromItem(item);
ItemDetailPresenter presenter = new ItemDetailPresenter();
DetailModel model = new DetailModel();
view.setPresenter(presenter);
presenter.setView(view);
presenter.setModel(model);
model.setPresenter(presenter);
replaceFragment(view, true, ItemDetailFragment.class.getName());
stateMaintainer.put(presenter);
stateMaintainer.put(model);
} }
private void replaceFragment(Fragment fragment, boolean addBackStack) { private void replaceFragment(Fragment fragment, boolean addBackStack, String tag) {
FragmentTransaction transaction = fragmentManager.beginTransaction(); FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.container, fragment, TAG); transaction.replace(R.id.container, fragment, tag);
if (addBackStack) if (addBackStack)
transaction.addToBackStack(null); transaction.addToBackStack(null);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit(); transaction.commit();
} }
} }

View File

@ -0,0 +1,97 @@
package hikapro.com.backpack;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.util.HashMap;
/**
* Created by tariel on 24/04/16.
*/
public class StateMaintainer {
protected final String TAG = getClass().getSimpleName();
private final String stateMaintainerTag;
private final WeakReference<FragmentManager> fragmentManager;
private StateMngFragment stateMngFragment;
private boolean isRecreating;
public StateMaintainer(FragmentManager fragmentManager, String stateMaintainerTAG) {
this.fragmentManager = new WeakReference<>(fragmentManager);
this.stateMaintainerTag = stateMaintainerTAG;
}
public boolean init() {
try {
stateMngFragment = (StateMngFragment)
fragmentManager.get().findFragmentByTag(stateMaintainerTag);
if (stateMngFragment == null) {
stateMngFragment = new StateMngFragment();
fragmentManager.get().beginTransaction()
.add(stateMngFragment, stateMaintainerTag).commit();
isRecreating = false;
return true;
} else {
isRecreating = true;
return false;
}
} catch (NullPointerException e) {
return false;
}
}
public boolean wasRecreated() { return isRecreating; }
public void put(String key, Object obj) {
stateMngFragment.put(key, obj);
}
public void put(Object obj) {
put(obj.getClass().getName(), obj);
}
public <T> T get(String key) {
return stateMngFragment.get(key);
}
public boolean hasKey(String key) {
return stateMngFragment.get(key) != null;
}
public static class StateMngFragment extends Fragment {
private HashMap<String, Object> data = new HashMap<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Grants that the fragment will be preserved
setRetainInstance(true);
}
public void put(String key, Object obj) {
data.put(key, obj);
Log.i(this.toString(), String.format("Put object %s Total count %d", key, data.size()));
}
public void put(Object object) {
put(object.getClass().getName(), object);
}
@SuppressWarnings("unchecked")
public <T> T get(String key) {
Log.i(this.toString(), String.format("Get object %s Total count %d", key, data.size()));
return (T) data.get(key);
}
}
}

View File

@ -0,0 +1,69 @@
package hikapro.com.backpack.model;
import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.presenter.Presenter;
/**
* Created by tariel on 23/04/16.
*/
public class DetailModel implements Model.Detail {
private Presenter.ItemDetail presenter;
private Item item;
public DetailModel() {
}
// detail -->
@Override
public int getCount() {
return 1;
}
@Override
public Item findItem(int id) {
return item;
}
// detail <--
// events -->
@Override
public void notifyDataSetChanged() {
presenter.notifyDataSetChanged();
}
@Override
public void onDestroy(boolean isConfigurationChanging) {
if ( !isConfigurationChanging ) {
presenter = null;
}
}
@Override
public void sendMessage(String message) {
presenter.showMessage(message);
}
// events <--
// process -->
@Override
public void executeQuery() {
notifyDataSetChanged();
}
// process <--
@Override
public void setPresenter(Presenter.ItemDetail presenter) {
this.presenter = presenter;
this.item = presenter.getCurrentItem();
}
@Override
public Presenter.ItemDetail getPresenter() {
return presenter;
}
}

View File

@ -27,9 +27,8 @@ public class ItemModel implements Model.Item {
private Hashtable<Category, List<Item>> items; private Hashtable<Category, List<Item>> items;
public ItemModel(Presenter.ItemList presenter) { public ItemModel() {
this.api = RestClient.getApi(); this.api = RestClient.getApi();
this.presenter = presenter;
this.rawCategories = new ArrayList<>(); this.rawCategories = new ArrayList<>();
this.rawItems = new ArrayList<>(); this.rawItems = new ArrayList<>();
this.sortedCategories = new ArrayList<>(); this.sortedCategories = new ArrayList<>();
@ -59,8 +58,15 @@ public class ItemModel implements Model.Item {
return false; return false;
} }
@Override @Override
public Item findItem(int id) { // TODO rename to find public Item findItem(int id) {
return null; Item item = null;
for (Item i : rawItems) {
if (i.getId() == id) {
item = i;
break;
}
}
return item;
} }
@Override @Override
public Item getItemByPosition(int categoryId, int position) { public Item getItemByPosition(int categoryId, int position) {
@ -91,7 +97,9 @@ public class ItemModel implements Model.Item {
@Override @Override
public void onDestroy(boolean isConfigurationChanging) { public void onDestroy(boolean isConfigurationChanging) {
if ( !isConfigurationChanging ) {
presenter = null;
}
} }
@Override @Override
public void sendMessage(String message) { public void sendMessage(String message) {
@ -103,8 +111,13 @@ public class ItemModel implements Model.Item {
@Override @Override
public void executeQuery() { public void executeQuery() {
if (rawCategories.isEmpty() || rawItems.isEmpty()) {
loadCategories(); loadCategories();
loadItems(); loadItems();
} else {
notifyDataSetChanged();
}
} }
private void loadCategories() { private void loadCategories() {
Call<List<Category>> call = api.getItemCategories(); Call<List<Category>> call = api.getItemCategories();
@ -142,6 +155,17 @@ public class ItemModel implements Model.Item {
// other --> // other -->
@Override
public void setPresenter(Presenter.ItemList presenter) {
this.presenter = presenter;
}
@Override
public Presenter.ItemList getPresenter() {
return presenter;
}
private void initData() { private void initData() {
List<Integer> ids = presenter.getCurrentSet().getItems(); List<Integer> ids = presenter.getCurrentSet().getItems();
List<Item> sortedItems = new ArrayList<>(ids.size()); List<Item> sortedItems = new ArrayList<>(ids.size());

View File

@ -5,6 +5,7 @@ import java.util.List;
import hikapro.com.backpack.model.entities.Category; import hikapro.com.backpack.model.entities.Category;
import hikapro.com.backpack.model.entities.Item; import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.model.entities.Set; import hikapro.com.backpack.model.entities.Set;
import hikapro.com.backpack.presenter.Presenter;
/** /**
* Created by tariel on 19/04/16. * Created by tariel on 19/04/16.
@ -22,6 +23,8 @@ public interface Model {
hikapro.com.backpack.model.entities.Set findSet(int id); hikapro.com.backpack.model.entities.Set findSet(int id);
int getSetsCount(); int getSetsCount();
void notifyDataSetChanged(); void notifyDataSetChanged();
void setPresenter(Presenter.SetList presenter);
Presenter.SetList getPresenter();
} }
interface Item extends Base { interface Item extends Base {
@ -33,6 +36,16 @@ public interface Model {
hikapro.com.backpack.model.entities.Category getCategoryByPosition(int position); hikapro.com.backpack.model.entities.Category getCategoryByPosition(int position);
int getCategoriesCount(); int getCategoriesCount();
void notifyDataSetChanged(); void notifyDataSetChanged();
void setPresenter(Presenter.ItemList presenter);
Presenter.ItemList getPresenter();
}
interface Detail extends Base {
int getCount();
hikapro.com.backpack.model.entities.Item findItem(int id);
void notifyDataSetChanged();
void setPresenter(Presenter.ItemDetail presenter);
Presenter.ItemDetail getPresenter();
} }
} }

View File

@ -18,10 +18,9 @@ public class SetModel implements Model.Set {
private Api api; private Api api;
private Presenter.SetList presenter; private Presenter.SetList presenter;
public SetModel(Presenter.SetList presenter) { public SetModel() {
this.api = RestClient.getApi(); this.api = RestClient.getApi();
this.iList = new ArrayList<>(); this.iList = new ArrayList<>();
this.presenter = presenter;
} }
// sets --> // sets -->
@ -53,6 +52,9 @@ public class SetModel implements Model.Set {
@Override @Override
public void onDestroy(boolean isConfigurationChanging) { public void onDestroy(boolean isConfigurationChanging) {
if ( !isConfigurationChanging ) {
presenter = null;
}
} }
@Override @Override
@ -71,6 +73,13 @@ public class SetModel implements Model.Set {
@Override @Override
public void executeQuery() { public void executeQuery() {
if (iList.isEmpty())
loadSets();
else
notifyDataSetChanged();
}
private void loadSets() {
Call<List<hikapro.com.backpack.model.entities.Set>> call = api.getSets(); Call<List<hikapro.com.backpack.model.entities.Set>> call = api.getSets();
call.enqueue(new Callback<List<hikapro.com.backpack.model.entities.Set>>() { call.enqueue(new Callback<List<hikapro.com.backpack.model.entities.Set>>() {
@Override @Override
@ -91,6 +100,17 @@ public class SetModel implements Model.Set {
// process <-- // process <--
// other --> // other -->
@Override
public void setPresenter(Presenter.SetList presenter) {
this.presenter = presenter;
}
@Override
public Presenter.SetList getPresenter() {
return presenter;
}
// other <-- // other <--

View File

@ -3,13 +3,14 @@ package hikapro.com.backpack.model.entities;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Created by tariel on 02/04/16. * Created by tariel on 02/04/16.
*/ */
public class Item implements Comparable<Item> { public class Item implements Comparable<Item>, Serializable {
@SerializedName("id") @SerializedName("id")
@Expose @Expose

View File

@ -0,0 +1,147 @@
package hikapro.com.backpack.presenter;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Toast;
import java.lang.ref.WeakReference;
import hikapro.com.backpack.R;
import hikapro.com.backpack.model.Model;
import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.presenter.adapters.ItemDetailAdapter;
import hikapro.com.backpack.view.View;
import hikapro.com.backpack.view.recycler.DetailViewHolder;
/**
* Created by tariel on 23/04/16.
*/
public class ItemDetailPresenter implements Presenter.ItemDetail {
private WeakReference<View.ItemDetail> view;
private Model.Detail model;
private ItemDetailAdapter adapter;
private Item item;
public ItemDetailPresenter() {
this.adapter = new ItemDetailAdapter(this);
}
// life cycle -->
@Override
public void onDestroy(boolean isChangingConfiguration) {
view = null;
model.onDestroy(isChangingConfiguration);
if ( !isChangingConfiguration ) {
model = null;
}
}
@Override
public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
android.view.View view = inflater.inflate(R.layout.fragment_item_detail, container, false);
LinearLayoutManager llm = new LinearLayoutManager(getActivityContext());
RecyclerView detailRecycler = (RecyclerView) view.findViewById(R.id.item_detail_recycler);
detailRecycler.setLayoutManager(llm);
detailRecycler.setAdapter(adapter);
detailRecycler.setItemAnimator(new DefaultItemAnimator());
model.executeQuery();
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
}
// life cycle <--
// recycler -->
@Override
public int getItemsCount() {
return model.getCount();
}
@Override
public void bindViewHolder(DetailViewHolder holder, int position) {
hikapro.com.backpack.model.entities.Item item = model.findItem(position);
holder.title.setText(item.getName());
holder.description.setText(item.getDescription());
holder.title.setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(android.view.View view) {
showMessage("On detail click");
}
});
}
@Override
public DetailViewHolder createViewHolder(ViewGroup parent, int viewType) {
DetailViewHolder viewHolder;
android.view.View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_detail,
parent, false);
viewHolder = new DetailViewHolder(v);
return viewHolder;
}
// recycler <--
// process -->
@Override
public void notifyDataSetChanged() {
adapter.notifyDataSetChanged();
}
// process <--
// other impl -->
@Override
public void setView(View.ItemDetail view) {
this.view = new WeakReference<>(view);
this.item = getView().getItem();
}
@Override
public void setModel(Model.Detail model) {
this.model = model;
}
@Override
public Item getCurrentItem() {
return item;
}
@Override
public Context getAppContext() {
try {
return getView().getAppContext();
} catch (NullPointerException e) {
return null;
}
}
@Override
public Context getActivityContext() {
try {
return getView().getActivityContext();
} catch (NullPointerException e) {
return null;
}
}
@Override
public void showMessage(String message) {
Toast.makeText(getView().getAppContext(), message, Toast.LENGTH_SHORT).show();
}
// other impl <--
private View.ItemDetail getView() throws NullPointerException {
if ( view != null )
return view.get();
else
throw new NullPointerException("View is unavailable");
}
}

View File

@ -16,6 +16,7 @@ import java.util.List;
import hikapro.com.backpack.R; import hikapro.com.backpack.R;
import hikapro.com.backpack.model.ItemModel; import hikapro.com.backpack.model.ItemModel;
import hikapro.com.backpack.model.Model; import hikapro.com.backpack.model.Model;
import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.model.entities.Set; import hikapro.com.backpack.model.entities.Set;
import hikapro.com.backpack.presenter.adapters.CategoryListAdapter; import hikapro.com.backpack.presenter.adapters.CategoryListAdapter;
import hikapro.com.backpack.presenter.adapters.ItemListAdapter; import hikapro.com.backpack.presenter.adapters.ItemListAdapter;
@ -35,11 +36,8 @@ public class ItemListPresenter implements Presenter.ItemList {
private Set set; private Set set;
private CategoryListAdapter categoryListAdapter; private CategoryListAdapter categoryListAdapter;
public ItemListPresenter(View.ItemList view, Set set) { public ItemListPresenter() {
this.view = new WeakReference<>(view);
this.set = set;
this.categoryListAdapter = new CategoryListAdapter(this); this.categoryListAdapter = new CategoryListAdapter(this);
setModel(new ItemModel(this));
} }
// life cycle --> // life cycle -->
@ -113,7 +111,7 @@ public class ItemListPresenter implements Presenter.ItemList {
holder.title.setOnClickListener(new android.view.View.OnClickListener() { holder.title.setOnClickListener(new android.view.View.OnClickListener() {
@Override @Override
public void onClick(android.view.View view) { public void onClick(android.view.View view) {
showMessage("Position " + position + " Id " + holder.id); clickItem(holder.id);
} }
}); });
} }
@ -121,6 +119,11 @@ public class ItemListPresenter implements Presenter.ItemList {
public int getItemsCount(int categoryId) { public int getItemsCount(int categoryId) {
return model.getItemsCount(categoryId);//TODO category Id return model.getItemsCount(categoryId);//TODO category Id
} }
@Override
public int getCategoriesCount() {
return model.getCategoriesCount();
}
// recycler <-- // recycler <--
@ -132,6 +135,14 @@ public class ItemListPresenter implements Presenter.ItemList {
categoryListAdapter.notifyItemAdapters(); categoryListAdapter.notifyItemAdapters();
} }
@Override
public void clickItem(int itemId) {
Item item = model.findItem(itemId);
if (item != null)
getView().showItemDetail(item);
else
showMessage(String.format("Item with Id %d is not found.", itemId));
}
// process <-- // process <--
// other impl --> // other impl -->
@ -139,6 +150,11 @@ public class ItemListPresenter implements Presenter.ItemList {
@Override @Override
public void setView(View.ItemList view) { public void setView(View.ItemList view) {
this.view = new WeakReference<>(view); this.view = new WeakReference<>(view);
this.set = getView().getSet();
}
@Override
public void setModel(Model.Item model) {
this.model = model;
} }
@Override @Override
public Context getAppContext() { public Context getAppContext() {
@ -157,10 +173,6 @@ public class ItemListPresenter implements Presenter.ItemList {
} }
} }
@Override @Override
public void setModel(Model.Item model) {
this.model = model;
}
@Override
public void showMessage(String message) { public void showMessage(String message) {
Toast.makeText(getView().getAppContext(), message, Toast.LENGTH_SHORT).show(); Toast.makeText(getView().getAppContext(), message, Toast.LENGTH_SHORT).show();
} }
@ -174,10 +186,6 @@ public class ItemListPresenter implements Presenter.ItemList {
throw new NullPointerException("View is unavailable"); throw new NullPointerException("View is unavailable");
} }
@Override
public int getCategoriesCount() {
return model.getCategoriesCount();
}
@Override @Override
public Set getCurrentSet() { public Set getCurrentSet() {

View File

@ -6,8 +6,10 @@ import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
import hikapro.com.backpack.model.Model; import hikapro.com.backpack.model.Model;
import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.model.entities.Set; import hikapro.com.backpack.model.entities.Set;
import hikapro.com.backpack.view.recycler.CategoryViewHolder; import hikapro.com.backpack.view.recycler.CategoryViewHolder;
import hikapro.com.backpack.view.recycler.DetailViewHolder;
import hikapro.com.backpack.view.recycler.ItemViewHolder; import hikapro.com.backpack.view.recycler.ItemViewHolder;
import hikapro.com.backpack.view.recycler.SetViewHolder; import hikapro.com.backpack.view.recycler.SetViewHolder;
@ -49,6 +51,23 @@ public interface Presenter {
Set getCurrentSet(); Set getCurrentSet();
void showMessage(String message); void showMessage(String message);
void onSaveInstanceState(Bundle outState); void onSaveInstanceState(Bundle outState);
void clickItem(int itemId);
}
interface ItemDetail extends Base {
void setView(hikapro.com.backpack.view.View.ItemDetail view);
void setModel(Model.Detail model);
void notifyDataSetChanged();
void showMessage(String message);
int getItemsCount();
void bindViewHolder(DetailViewHolder holder, int position);
DetailViewHolder createViewHolder(ViewGroup parent, int viewType);
void onDestroy(boolean isChangingConfiguration);
android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
void onSaveInstanceState(Bundle outState);
Item getCurrentItem();
} }

View File

@ -30,7 +30,6 @@ public class SetListPresenter implements Presenter.SetList {
public SetListPresenter() { public SetListPresenter() {
this.adapter = new SetListAdapter(this); this.adapter = new SetListAdapter(this);
setModel(new SetModel(this));
} }
// life cycle --> // life cycle -->

View File

@ -0,0 +1,40 @@
package hikapro.com.backpack.presenter.adapters;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import hikapro.com.backpack.presenter.Presenter;
import hikapro.com.backpack.view.recycler.DetailViewHolder;
/**
* Created by tariel on 23/04/16.
*/
public class ItemDetailAdapter extends RecyclerView.Adapter<DetailViewHolder> {
private Presenter.ItemDetail presenter;
private int itemId;
public ItemDetailAdapter(Presenter.ItemDetail presenter) {
this.presenter = presenter;
}
@Override
public int getItemCount() {
return presenter.getItemsCount();
}
@Override
public void onBindViewHolder(DetailViewHolder holder, int position) {
presenter.bindViewHolder(holder, position);
}
@Override
public DetailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return presenter.createViewHolder(parent, viewType);
}
public void setItemId(int id) {
this.itemId = id;
}
}

View File

@ -24,13 +24,16 @@ public interface View {
interface ItemList extends Base { interface ItemList extends Base {
void showItemDetail(Item item); void showItemDetail(Item item);
void setPresenter(Presenter.ItemList presenter); void setPresenter(Presenter.ItemList presenter);
Set getSet();
} }
interface ItemDetail extends Base { interface ItemDetail extends Base {
void setPresenter(Presenter.ItemDetail presenter);
Item getItem();
} }
interface ActivityCallback { interface ActivityCallback {
void startSetListFragment();
void startItemListFragment(Set set); void startItemListFragment(Set set);
void startItemDetailFragment(); void startItemDetailFragment(Item item);
} }
} }

View File

@ -0,0 +1,145 @@
package hikapro.com.backpack.view.fragments;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import hikapro.com.backpack.model.entities.Item;
import hikapro.com.backpack.presenter.Presenter;
/**
* A simple {@link Fragment} subclass.
*/
public class ItemDetailFragment extends Fragment implements hikapro.com.backpack.view.View.ItemDetail {
private static final String BUNDLE_ITEM_KEY = "BUNDLE_ITEM_KEY";
private Presenter.ItemDetail presenter;
private hikapro.com.backpack.view.View.ActivityCallback activityCallback;
public ItemDetailFragment() {
// Required empty public constructor
}
protected static ItemDetailFragment construct() {
return new ItemDetailFragment();
}
public static ItemDetailFragment newFromItem(Item item) {
ItemDetailFragment ret = ItemDetailFragment.construct();
Bundle args = new Bundle();
args.putSerializable(BUNDLE_ITEM_KEY, item);
ret.setArguments(args);
return ret;
}
// life cycle -->
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
activityCallback = (hikapro.com.backpack.view.View.ActivityCallback) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement activityCallback");
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activityCallback = (hikapro.com.backpack.view.View.ActivityCallback) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement activityCallback");
}
Log.i(this.toString(), "onAttach");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(this.toString(), "onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = presenter.onCreateView(inflater, container, savedInstanceState);
presenter.setView(this);
Log.i(this.toString(), "onCreateView");
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(this.toString(), "onActivityCreated");
}
@Override
public void onStart() {
super.onStart();
Log.i(this.toString(), "onStart");
}
@Override
public void onResume() {
super.onResume();
Log.i(this.toString(), "onResume");
}
@Override
public void onStop() {
super.onStop();
Log.i(this.toString(), "onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
presenter.onDestroy(true); // TODO isChangingConfigurations
Log.i(this.toString(), "onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
presenter.onDestroy(false); // TODO isChangingConfigurations
Log.i(this.toString(), "onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
Log.i(this.toString(), "onDetach");
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(this.toString(), "onSaveInstanceState");
}
// life cycle <--
@Override
public void setPresenter(Presenter.ItemDetail presenter) {
this.presenter = presenter;
}
@Override
public Context getAppContext() {
return this.getActivity().getApplicationContext();
}
@Override
public Context getActivityContext() {
return this.getActivity();
}
@Override
public Item getItem() {
Bundle args = getArguments();
Item item = (Item) args.getSerializable(BUNDLE_ITEM_KEY);
return item;
}
}

View File

@ -24,7 +24,6 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v
private hikapro.com.backpack.view.View.ActivityCallback activityCallback; private hikapro.com.backpack.view.View.ActivityCallback activityCallback;
private Presenter.ItemList presenter; private Presenter.ItemList presenter;
public ItemListFragment() { public ItemListFragment() {
// Required empty public constructor // Required empty public constructor
} }
@ -38,7 +37,6 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putSerializable(BUNDLE_SET_KEY, set); args.putSerializable(BUNDLE_SET_KEY, set);
ret.setArguments(args); ret.setArguments(args);
ret.setPresenter(new ItemListPresenter(ret, set));
return ret; return ret;
} }
@ -74,6 +72,7 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v
Bundle savedInstanceState) { Bundle savedInstanceState) {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View view = presenter.onCreateView(inflater, container, savedInstanceState); View view = presenter.onCreateView(inflater, container, savedInstanceState);
presenter.setView(this);
Log.i(this.toString(), "onCreateView"); Log.i(this.toString(), "onCreateView");
return view; return view;
} }
@ -106,6 +105,7 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
presenter.onDestroy(false); // TODO isChangingConfigurations
Log.i(this.toString(), "onDestroy"); Log.i(this.toString(), "onDestroy");
} }
@Override @Override
@ -123,7 +123,7 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v
@Override @Override
public void showItemDetail(Item item) { public void showItemDetail(Item item) {
//TODO not implemented activityCallback.startItemDetailFragment(item);
} }
@Override @Override
@ -141,4 +141,9 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v
return this.getActivity(); return this.getActivity();
} }
public Set getSet() {
return (Set) getArguments().getSerializable(BUNDLE_SET_KEY);
}
} }

View File

@ -55,7 +55,6 @@ public class SetListFragment extends Fragment implements hikapro.com.backpack.vi
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setPresenter(new SetListPresenter());
Log.i(this.toString(), "onCreate"); Log.i(this.toString(), "onCreate");
} }
@Override @Override
@ -101,6 +100,7 @@ public class SetListFragment extends Fragment implements hikapro.com.backpack.vi
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
presenter.onDestroy(false); // TODO isChangingConfigurations
Log.i(this.toString(), "onDestroy"); Log.i(this.toString(), "onDestroy");
} }
@Override @Override

View File

@ -0,0 +1,29 @@
package hikapro.com.backpack.view.recycler;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import hikapro.com.backpack.R;
/**
* Created by tariel on 23/04/16.
*/
public class DetailViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public TextView description;
public ImageView photo;
public DetailViewHolder(View v) {
super(v);
setupViews(v);
}
private void setupViews(View view) {
title = (TextView) view.findViewById(R.id.item_title);
description = (TextView) view.findViewById(R.id.item_description);
photo = (ImageView) view.findViewById(R.id.item_photo);
}
}

View File

@ -0,0 +1,17 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="hikapro.com.backpack.view.fragments.ItemDetailFragment">
<android.support.v7.widget.RecyclerView
android:id="@+id/item_detail_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
</LinearLayout>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp">
<TextView
android:id="@+id/item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="@string/hello_blank_fragment" />
<ImageView
android:id="@+id/item_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/item_title"
android:layout_marginTop="25dp"
android:layout_centerInParent="true"
android:contentDescription="Photo is here"/>
<TextView
android:id="@+id/item_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/item_photo"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp"
android:text="@string/hello_blank_fragment" />
</RelativeLayout>

View File

@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
</style>
</resources>

View File

@ -1,3 +1,6 @@
<resources> <resources>
<string name="app_name">BackPack</string> <string name="app_name">BackPack</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources> </resources>

View File

@ -1,7 +1,7 @@
<resources> <resources>
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>