From 001889aa1481f15dd0d80feaef89d9aa54d362cc Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 4 Jan 2019 21:19:13 +0400 Subject: [PATCH] The application architecture was refactored (the application now uses the MVP architectural pattern), and dynamic loading of all levels of the tree is implemented. --- .idea/caches/build_file_checksums.ser | Bin 537 -> 537 bytes .idea/misc.xml | 2 +- app/build.gradle | 5 + app/src/main/AndroidManifest.xml | 6 +- .../ru/volgorobot/vrcatalog/MainActivity.java | 247 ------------------ .../ru/volgorobot/vrcatalog/MainContract.java | 32 +++ .../volgorobot/vrcatalog/MainPresenter.java | 59 +++++ .../vrcatalog/additional/NodeViewFactory.java | 14 +- .../volgorobot/vrcatalog/api/Controller.java | 5 +- .../volgorobot/vrcatalog/model/CoreModel.java | 80 ++++++ .../vrcatalog/model/FirstLevelModel.java | 3 + .../vrcatalog/model/SecondLevelModel.java | 3 + .../vrcatalog/model/ThirdLevelModel.java | 3 + .../FirstLevelNodeViewBinder.java | 47 +++- .../SecondLevelNodeViewBinder.java | 48 +++- .../vrcatalog/{ => view}/AboutActivity.java | 4 +- .../vrcatalog/view/MainActivity.java | 156 +++++++++++ .../{ => view}/SettingsActivity.java | 4 +- app/src/main/res/layout/activity_about.xml | 2 +- app/src/main/res/layout/app_bar_main.xml | 2 +- app/src/main/res/layout/content_main.xml | 2 +- 21 files changed, 456 insertions(+), 268 deletions(-) delete mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/MainActivity.java create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/MainPresenter.java create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java rename app/src/main/java/ru/volgorobot/vrcatalog/{ => view}/AboutActivity.java (92%) create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java rename app/src/main/java/ru/volgorobot/vrcatalog/{ => view}/SettingsActivity.java (93%) diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index ef96a8505cdab6aa364ad4da6e4cda1a42b9a674..33a95c05574a131d0f93a7b0ee0ed30a2f7bd9cf 100644 GIT binary patch delta 33 rcmV++0N($Z1epYom;@PTL9Vf!YylC4l68)huDINEbJ2}+au@~c&V~jmH@x4!^mkg!#*SZc6#&nI4rBlT diff --git a/.idea/misc.xml b/.idea/misc.xml index e0d5b93..b0c7b20 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -29,7 +29,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 3d8f62f..70affef 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,6 +10,10 @@ android { versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } buildTypes { release { minifyEnabled false @@ -24,6 +28,7 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:design:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.github.msteinbeck:sig4j:1.0.1' implementation 'me.texy.treeview:treeview_lib:1.0.4' implementation 'com.google.code.gson:gson:2.8.2' implementation 'com.squareup.retrofit2:retrofit:2.1.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5a9a658..6b73d4a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> @@ -21,8 +21,8 @@ - - + + \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/MainActivity.java deleted file mode 100644 index 7ff9c58..0000000 --- a/app/src/main/java/ru/volgorobot/vrcatalog/MainActivity.java +++ /dev/null @@ -1,247 +0,0 @@ -package ru.volgorobot.vrcatalog; - -import android.content.AsyncQueryHandler; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.AsyncTask; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.design.widget.NavigationView; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Toast; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import me.texy.treeview.TreeNode; -import me.texy.treeview.TreeView; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import ru.volgorobot.vrcatalog.additional.NodeViewFactory; -import ru.volgorobot.vrcatalog.api.Controller; -import ru.volgorobot.vrcatalog.api.VRApi; -import ru.volgorobot.vrcatalog.model.FirstLevelModel; -import ru.volgorobot.vrcatalog.model.SecondLevelModel; -import ru.volgorobot.vrcatalog.model.ThirdLevelModel; - -public class MainActivity extends AppCompatActivity - implements NavigationView.OnNavigationItemSelectedListener, SwipeRefreshLayout.OnRefreshListener { - - private TreeView treeView; - private VRApi vrApi; - private List firstLevelObjects = new ArrayList<>(); - private List firstLevelNodes = new ArrayList<>(); - private List secondLevelObjects = new ArrayList<>(); - private List thirdLevelObjects = new ArrayList<>(); - - private TreeNode rootNode = TreeNode.root(); - private SwipeRefreshLayout mSwipeRefreshLayout; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - - DrawerLayout drawer = findViewById(R.id.drawer_layout); - ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( - this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); - drawer.addDrawerListener(toggle); - toggle.syncState(); - - NavigationView navigationView = findViewById(R.id.nav_view); - navigationView.setNavigationItemSelectedListener(this); - - mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout); - mSwipeRefreshLayout.setOnRefreshListener(MainActivity.this); - mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); - - try { - getTreeData(false); - } catch (IllegalStateException e) { - // - } - treeView = new TreeView(rootNode, MainActivity.this, new NodeViewFactory()); - ((ViewGroup) findViewById(R.id.treeViewContainer)).addView(treeView.getView()); - } - - @Override - public void onBackPressed() { - DrawerLayout drawer = findViewById(R.id.drawer_layout); - if (drawer.isDrawerOpen(GravityCompat.START)) { - drawer.closeDrawer(GravityCompat.START); - } else { - super.onBackPressed(); - } - } - - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - - return super.onOptionsItemSelected(item); - } - - @SuppressWarnings("StatementWithEmptyBody") - @Override - public boolean onNavigationItemSelected(MenuItem item) { - // Handle navigation view item clicks here. - int id = item.getItemId(); - NavigationView navView = findViewById(R.id.nav_view); - - if (id == R.id.nav_settings) { - startActivity(new Intent(this, SettingsActivity.class)); - - } else if (id == R.id.nav_about) { - startActivity(new Intent(this, AboutActivity.class)); - } - - DrawerLayout drawer = findViewById(R.id.drawer_layout); - drawer.closeDrawer(GravityCompat.START); - return true; - } - - private void fillRootNode() { - for (int i = 0; i < firstLevelObjects.size(); i++) { - firstLevelNodes.add(new TreeNode(firstLevelObjects.get(i).getName())); - firstLevelNodes.get(i).setLevel(0); - firstLevelNodes.get(i).setChildren(getSecondLevelNodesByParentID(firstLevelObjects.get(i).getID())); - } - - rootNode.setChildren(firstLevelNodes); - } - - private ArrayList getSecondLevelNodesByParentID(int parentTypeID) { - ArrayList objects = new ArrayList<>(); - for (int i = 0; i < secondLevelObjects.size(); i++) { - if(secondLevelObjects.get(i).getDetailTypeId() == parentTypeID) { - objects.add(secondLevelObjects.get(i)); - } - } - ArrayList nodes = new ArrayList<>(); - for (int i = 0; i < objects.size(); i++) { - nodes.add(new TreeNode(objects.get(i).getName())); - nodes.get(i).setLevel(1); - } - return nodes; - } - - private ArrayList getThirdLevelNodesByParentName(String parentName) { - ArrayList objects = new ArrayList<>(); - for (int i = 0; i < thirdLevelObjects.size(); i++) { - if(thirdLevelObjects.get(i).getName().equals(parentName)) { - objects.add(thirdLevelObjects.get(i)); - } - } - ArrayList nodes = new ArrayList<>(); - for (int i = 0; i < objects.size(); i++) { - nodes.add(new TreeNode(objects.get(i).getName())); - nodes.get(i).setLevel(2); - } - return nodes; - } - - @Override - public void onRefresh() { - mSwipeRefreshLayout.setRefreshing(true); - - try { - getTreeData(true); - } catch (IllegalStateException e) { - // - } - } - - private void getTreeData(final boolean clean) throws IllegalStateException { - mSwipeRefreshLayout.setRefreshing(true); - if(clean) { - firstLevelNodes.removeAll(firstLevelNodes); - firstLevelObjects.removeAll(firstLevelObjects); - secondLevelObjects.removeAll(secondLevelObjects); - } - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - String baseURL = sharedPreferences.getString("addressOfServer", ""); - - try { - vrApi = Controller.getApi(baseURL, this); - } catch(IllegalStateException e) { - throw new IllegalStateException(); - } - class GetTreeData extends AsyncTask { - @Override - protected Integer doInBackground(Void... voids) { - try { - Response> firstLevelResponse = vrApi.getFirstLevel().execute(); - if(firstLevelResponse.isSuccessful()) { - firstLevelObjects.addAll(firstLevelResponse.body()); - for (int i = 0; i < firstLevelObjects.size(); i++) { - Response> secondLevelResponse = vrApi.getSecondLevel(firstLevelObjects.get(i).getID()).execute(); - if(secondLevelResponse.isSuccessful()) { - secondLevelObjects.addAll(secondLevelResponse.body()); - } else { - return 2; - } - } - } else { - return 2; - } - } catch (Exception e) { - return 1; - } - return 0; - } - - @Override - protected void onPostExecute(Integer integer) { - super.onPostExecute(integer); - if(integer == 0) { - fillRootNode(); - treeView.refreshTreeView(); - mSwipeRefreshLayout.setRefreshing(false); - } else if(integer == 1) { - onFailureAnswer(1); - } else if(integer == 2) { - onFailureAnswer(2); - } - - } - } - new GetTreeData().execute(); - } - - private void onFailureAnswer(int errorCode) { - switch (errorCode) { - case 1: { - Toast.makeText(MainActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); - Log.e("VRCatalog", "Network Error! Re-check your connection credentials or network settings! Technical info: null"); - mSwipeRefreshLayout.setRefreshing(false); - break; - } - case 2: { - Toast.makeText(MainActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); - Log.e("VRCatalog", "Answer of server is wrong! Re-check your connection credentials! Technical info: null"); - mSwipeRefreshLayout.setRefreshing(false); - break; - } - } - } - -} - - diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java b/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java new file mode 100644 index 0000000..cfabe87 --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java @@ -0,0 +1,32 @@ +package ru.volgorobot.vrcatalog; + +import android.widget.ImageView; + +import com.github.msteinbeck.sig4j.signal.Signal1; + +import java.util.ArrayList; + +import ru.volgorobot.vrcatalog.model.FirstLevelModel; +import ru.volgorobot.vrcatalog.model.SecondLevelModel; +import ru.volgorobot.vrcatalog.model.ThirdLevelModel; + +public interface MainContract { + interface MainActivityView { + void swipeLayoutSetRefreshing(boolean state); + void buildFirstLevelTree(ArrayList firstLevelModels); + void onFailureAnswer(int errorCode); + void refreshTree(); + } + + interface Presenter { + void getFirstLevel(); + void failureAnswerSlot(int errorCode); + } + + interface MainModel { + Signal1 errorSignal = new Signal1<>(); + ArrayList getFirstLevel(); + ArrayList getSecondLevelByParentID(int parentID); + ArrayList getThirdLevelByParentID(int parentID); + } +} diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/MainPresenter.java b/app/src/main/java/ru/volgorobot/vrcatalog/MainPresenter.java new file mode 100644 index 0000000..eba079a --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/MainPresenter.java @@ -0,0 +1,59 @@ +package ru.volgorobot.vrcatalog; + +import android.content.Context; +import android.os.AsyncTask; + +import java.util.ArrayList; + +import ru.volgorobot.vrcatalog.model.CoreModel; +import ru.volgorobot.vrcatalog.model.FirstLevelModel; + +public class MainPresenter implements MainContract.Presenter { + private MainContract.MainActivityView mView; + private MainContract.MainModel coreModel; + + public MainPresenter(MainContract.MainActivityView mainActivityView, Context context) { + this.mView = mainActivityView; + try { + this.coreModel = new CoreModel(context); + } catch (IllegalStateException e) { + mView.onFailureAnswer(3); + } + coreModel.errorSignal.connect(this::failureAnswerSlot); + } + + @Override + public void getFirstLevel() { + new AsyncTask>() { + @Override + protected ArrayList doInBackground(Void... voids) { + ArrayList firstLevelModels = coreModel.getFirstLevel(); + return firstLevelModels; + } + + @Override + protected void onPostExecute(ArrayList firstLevelModels) { + mView.buildFirstLevelTree(firstLevelModels); + } + }.execute(); + mView.swipeLayoutSetRefreshing(false); + } + + @Override + public void failureAnswerSlot(int errorCode) { + switch (errorCode) { + case 1: { + mView.onFailureAnswer(1); + break; + } + case 2: { + mView.onFailureAnswer(2); + break; + } + case 3: { + mView.onFailureAnswer(3); + break; + } + } + } +} diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/additional/NodeViewFactory.java b/app/src/main/java/ru/volgorobot/vrcatalog/additional/NodeViewFactory.java index caba708..0537306 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/additional/NodeViewFactory.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/additional/NodeViewFactory.java @@ -1,21 +1,31 @@ package ru.volgorobot.vrcatalog.additional; +import android.content.Context; import android.view.View; import me.texy.treeview.base.BaseNodeViewBinder; import me.texy.treeview.base.BaseNodeViewFactory; +import ru.volgorobot.vrcatalog.MainContract; import ru.volgorobot.vrcatalog.nodeViewBinders.FirstLevelNodeViewBinder; import ru.volgorobot.vrcatalog.nodeViewBinders.SecondLevelNodeViewBinder; import ru.volgorobot.vrcatalog.nodeViewBinders.ThirdLevelNodeViewBinder; public class NodeViewFactory extends BaseNodeViewFactory { + MainContract.MainActivityView mView; + Context context; + + public NodeViewFactory(Context context, MainContract.MainActivityView mView) { + this.mView = mView; + this.context = context; + } + @Override public BaseNodeViewBinder getNodeViewBinder(View view, int level) { switch (level) { case 0: - return new FirstLevelNodeViewBinder(view); + return new FirstLevelNodeViewBinder(view, context, mView); case 1: - return new SecondLevelNodeViewBinder(view); + return new SecondLevelNodeViewBinder(view, context, mView); case 2: return new ThirdLevelNodeViewBinder(view); default: diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/api/Controller.java b/app/src/main/java/ru/volgorobot/vrcatalog/api/Controller.java index 317ce52..3a1654a 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/api/Controller.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/api/Controller.java @@ -11,14 +11,12 @@ import retrofit2.converter.gson.GsonConverterFactory; public class Controller { private static String baseURL; - private static Context context; private static Retrofit retrofit; private static VRApi vrApi; - public static VRApi getApi(String baseURL1, Context context1) throws IllegalStateException { + public static VRApi getApi(String baseURL1) throws IllegalStateException { baseURL = baseURL1; - context = context1; Gson gson = new GsonBuilder() .setLenient() .create(); @@ -38,7 +36,6 @@ public class Controller { .addConverterFactory(GsonConverterFactory.create(gson)) .build(); } catch(Exception e) { - Toast.makeText(context, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); throw new IllegalStateException(); } } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java b/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java new file mode 100644 index 0000000..8f24604 --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java @@ -0,0 +1,80 @@ +package ru.volgorobot.vrcatalog.model; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import com.github.msteinbeck.sig4j.signal.Signal1; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import retrofit2.Response; +import ru.volgorobot.vrcatalog.MainContract; +import ru.volgorobot.vrcatalog.api.Controller; +import ru.volgorobot.vrcatalog.api.VRApi; + +public class CoreModel implements MainContract.MainModel { + private Context context; + private VRApi vrApi; + public final Signal1 errorSignal = new Signal1<>(); + + public CoreModel(Context context) throws IllegalStateException { + this.context = context; + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + String baseURL = sharedPreferences.getString("addressOfServer", ""); + try { + vrApi = Controller.getApi(baseURL); + } catch(IllegalStateException e) { + throw new IllegalStateException(); + } + } + + @Override + public ArrayList getFirstLevel() { + final ArrayList firstLevelModels = new ArrayList<>(); + try { + Response> response = vrApi.getFirstLevel().execute(); + if(response.isSuccessful()) { + firstLevelModels.addAll(response.body()); + } else { + errorSignal.emit(2); + } + } catch (IOException e) { + errorSignal.emit(1); + } + return firstLevelModels; + } + + @Override + public ArrayList getSecondLevelByParentID(int parentID) { + final ArrayList secondLevelModels = new ArrayList<>(); + try { + Response> response = vrApi.getSecondLevel(parentID).execute(); + if(response.isSuccessful()) { + secondLevelModels.addAll(response.body()); + } else { + errorSignal.emit(2); + } + } catch (IOException e) { + errorSignal.emit(1); + } + return secondLevelModels; + } + + @Override + public ArrayList getThirdLevelByParentID(int parentID) { + final ArrayList thirdLevelModels = new ArrayList<>(); + try { + Response> response = vrApi.getDetails(parentID).execute(); + if(response.isSuccessful()) { + thirdLevelModels.addAll(response.body()); + } else { + errorSignal.emit(2); + } + } catch (IOException e) { + errorSignal.emit(1); + } + return thirdLevelModels; + } +} diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/model/FirstLevelModel.java b/app/src/main/java/ru/volgorobot/vrcatalog/model/FirstLevelModel.java index b5579b4..3b467f7 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/model/FirstLevelModel.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/model/FirstLevelModel.java @@ -40,4 +40,7 @@ public class FirstLevelModel { this.iD = iD; } + public String toString() { + return name; + } } \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/model/SecondLevelModel.java b/app/src/main/java/ru/volgorobot/vrcatalog/model/SecondLevelModel.java index c002540..51cfb71 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/model/SecondLevelModel.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/model/SecondLevelModel.java @@ -51,4 +51,7 @@ public class SecondLevelModel { this.name = name; } + public String toString() { + return name; + } } \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/model/ThirdLevelModel.java b/app/src/main/java/ru/volgorobot/vrcatalog/model/ThirdLevelModel.java index 11c2c7d..c8898de 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/model/ThirdLevelModel.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/model/ThirdLevelModel.java @@ -59,4 +59,7 @@ public class ThirdLevelModel { this.name = name; } + public String toString() { + return name; + } } \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/FirstLevelNodeViewBinder.java b/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/FirstLevelNodeViewBinder.java index edc69ec..c08768f 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/FirstLevelNodeViewBinder.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/FirstLevelNodeViewBinder.java @@ -1,21 +1,34 @@ package ru.volgorobot.vrcatalog.nodeViewBinders; +import android.content.Context; +import android.os.AsyncTask; import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import java.util.ArrayList; + import me.texy.treeview.TreeNode; import me.texy.treeview.base.BaseNodeViewBinder; +import ru.volgorobot.vrcatalog.MainContract; import ru.volgorobot.vrcatalog.R; +import ru.volgorobot.vrcatalog.model.CoreModel; +import ru.volgorobot.vrcatalog.model.FirstLevelModel; +import ru.volgorobot.vrcatalog.model.SecondLevelModel; public class FirstLevelNodeViewBinder extends BaseNodeViewBinder { TextView textView; ImageView imageView; + CoreModel coreModel; + MainContract.MainActivityView mView; - public FirstLevelNodeViewBinder(View itemView) { + public FirstLevelNodeViewBinder(View itemView, Context context, MainContract.MainActivityView mView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.node_name_view); imageView = (ImageView) itemView.findViewById(R.id.arrow_img); + this.coreModel = new CoreModel(context); + this.mView = mView; + coreModel.errorSignal.connect(mView::onFailureAnswer); } @Override @@ -30,8 +43,36 @@ public class FirstLevelNodeViewBinder extends BaseNodeViewBinder { @Override public void onNodeToggled(TreeNode treeNode, boolean expand) { - if (expand) { - imageView.animate().rotation(90).setDuration(200).start(); + if(expand) { + FirstLevelModel firstLevelModel = (FirstLevelModel) treeNode.getValue(); + new AsyncTask>() { + @Override + protected void onPreExecute() { + super.onPreExecute(); + mView.swipeLayoutSetRefreshing(true); + } + + @Override + protected ArrayList doInBackground(Void... voids) { + ArrayList secondLevelModels = coreModel.getSecondLevelByParentID(firstLevelModel.getID()); + return secondLevelModels; + } + + @Override + protected void onPostExecute(ArrayList secondLevelModels) { + super.onPostExecute(secondLevelModels); + ArrayList treeNodes = new ArrayList<>(); + for (int i = 0; i < secondLevelModels.size(); i++) { + TreeNode treeNode1 = new TreeNode(secondLevelModels.get(i)); + treeNode1.setLevel(1); + treeNodes.add(treeNode1); + } + treeNode.setChildren(treeNodes); + mView.refreshTree(); + mView.swipeLayoutSetRefreshing(false); + imageView.animate().rotation(90).setDuration(200).start(); + } + }.execute(); } else { imageView.animate().rotation(0).setDuration(200).start(); } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/SecondLevelNodeViewBinder.java b/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/SecondLevelNodeViewBinder.java index 2b55270..cfd07c7 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/SecondLevelNodeViewBinder.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/nodeViewBinders/SecondLevelNodeViewBinder.java @@ -1,21 +1,35 @@ package ru.volgorobot.vrcatalog.nodeViewBinders; +import android.content.Context; +import android.os.AsyncTask; import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import java.util.ArrayList; + import me.texy.treeview.TreeNode; import me.texy.treeview.base.BaseNodeViewBinder; +import ru.volgorobot.vrcatalog.MainContract; import ru.volgorobot.vrcatalog.R; +import ru.volgorobot.vrcatalog.model.CoreModel; +import ru.volgorobot.vrcatalog.model.SecondLevelModel; +import ru.volgorobot.vrcatalog.model.ThirdLevelModel; public class SecondLevelNodeViewBinder extends BaseNodeViewBinder { TextView textView; ImageView imageView; + MainContract.MainModel coreModel; + MainContract.MainActivityView mView; - public SecondLevelNodeViewBinder(View itemView) { + + public SecondLevelNodeViewBinder(View itemView, Context context, MainContract.MainActivityView mView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.node_name_view); imageView = (ImageView) itemView.findViewById(R.id.arrow_img); + this.coreModel = new CoreModel(context); + this.mView = mView; + coreModel.errorSignal.connect(mView::onFailureAnswer); } @Override @@ -31,8 +45,36 @@ public class SecondLevelNodeViewBinder extends BaseNodeViewBinder { @Override public void onNodeToggled(TreeNode treeNode, boolean expand) { - if (expand) { - imageView.animate().rotation(90).setDuration(200).start(); + if(expand) { + SecondLevelModel secondLevelModel = (SecondLevelModel) treeNode.getValue(); + new AsyncTask>() { + @Override + protected void onPreExecute() { + super.onPreExecute(); + mView.swipeLayoutSetRefreshing(true); + } + + @Override + protected ArrayList doInBackground(Void... voids) { + ArrayList thirdLevelModels = coreModel.getThirdLevelByParentID(secondLevelModel.getID()); + return thirdLevelModels; + } + + @Override + protected void onPostExecute(ArrayList thirdLevelModels) { + super.onPostExecute(thirdLevelModels); + ArrayList treeNodes = new ArrayList<>(); + for (int i = 0; i < thirdLevelModels.size(); i++) { + TreeNode treeNode1 = new TreeNode(thirdLevelModels.get(i)); + treeNode1.setLevel(2); + treeNodes.add(treeNode1); + } + treeNode.setChildren(treeNodes); + mView.refreshTree(); + mView.swipeLayoutSetRefreshing(false); + imageView.animate().rotation(90).setDuration(200).start(); + } + }.execute(); } else { imageView.animate().rotation(0).setDuration(200).start(); } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/AboutActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java similarity index 92% rename from app/src/main/java/ru/volgorobot/vrcatalog/AboutActivity.java rename to app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java index 817410f..a1496df 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/AboutActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java @@ -1,10 +1,12 @@ -package ru.volgorobot.vrcatalog; +package ru.volgorobot.vrcatalog.view; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; +import ru.volgorobot.vrcatalog.R; + public class AboutActivity extends AppCompatActivity { @Override diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java new file mode 100644 index 0000000..b0a21d1 --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java @@ -0,0 +1,156 @@ +package ru.volgorobot.vrcatalog.view; + +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.NavigationView; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.MenuItem; +import android.view.ViewGroup; +import android.widget.Toast; + +import java.util.ArrayList; + +import me.texy.treeview.TreeNode; +import me.texy.treeview.TreeView; +import ru.volgorobot.vrcatalog.MainContract; +import ru.volgorobot.vrcatalog.MainPresenter; +import ru.volgorobot.vrcatalog.R; +import ru.volgorobot.vrcatalog.additional.NodeViewFactory; +import ru.volgorobot.vrcatalog.model.FirstLevelModel; + +public class MainActivity extends AppCompatActivity + implements NavigationView.OnNavigationItemSelectedListener, SwipeRefreshLayout.OnRefreshListener, MainContract.MainActivityView { + + private MainContract.Presenter mPresenter; + private TreeView treeView; + private TreeNode rootNode = TreeNode.root(); + private SwipeRefreshLayout mSwipeRefreshLayout; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + DrawerLayout drawer = findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + drawer.addDrawerListener(toggle); + toggle.syncState(); + + NavigationView navigationView = findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout); + mSwipeRefreshLayout.setOnRefreshListener(MainActivity.this); + mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); + + mPresenter = new MainPresenter(this, MainActivity.this); + + treeView = new TreeView(rootNode, MainActivity.this, new NodeViewFactory(MainActivity.this, this)); + treeView.setItemAnimator(new DefaultItemAnimator()); + ((ViewGroup) findViewById(R.id.treeViewContainer)).addView(treeView.getView()); + mSwipeRefreshLayout.setRefreshing(true); + mPresenter.getFirstLevel(); + } + + @Override + public void onBackPressed() { + DrawerLayout drawer = findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else { + super.onBackPressed(); + } + } + + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + + return super.onOptionsItemSelected(item); + } + + @SuppressWarnings("StatementWithEmptyBody") + @Override + public boolean onNavigationItemSelected(MenuItem item) { + // Handle navigation view item clicks here. + int id = item.getItemId(); + NavigationView navView = findViewById(R.id.nav_view); + + if (id == R.id.nav_settings) { + startActivity(new Intent(this, SettingsActivity.class)); + + } else if (id == R.id.nav_about) { + startActivity(new Intent(this, AboutActivity.class)); + } + + DrawerLayout drawer = findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } + + + @Override + public void onRefresh() { + mSwipeRefreshLayout.setRefreshing(true); + mPresenter.getFirstLevel(); + } + + public void onFailureAnswer(int errorCode) { + switch (errorCode) { + case 1: { + Toast.makeText(MainActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); + Log.e("VRCatalog", "Network Error! Re-check your connection credentials or network settings! Technical info: null"); + mSwipeRefreshLayout.setRefreshing(false); + break; + } + case 2: { + Toast.makeText(MainActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); + Log.e("VRCatalog", "Answer of server is wrong! Re-check your connection credentials! Technical info: null"); + mSwipeRefreshLayout.setRefreshing(false); + break; + } + case 3: { + Toast.makeText(this, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); + mSwipeRefreshLayout.setRefreshing(false); + break; + } + } + } + + @Override + public void swipeLayoutSetRefreshing(boolean state) { + mSwipeRefreshLayout.setRefreshing(state); + } + + @Override + public void buildFirstLevelTree(ArrayList firstLevelModels) { + ArrayList treeNodes = new ArrayList<>(); + for (int i = 0; i < firstLevelModels.size(); i++) { + TreeNode treeNode = new TreeNode(firstLevelModels.get(i)); + treeNode.setLevel(0); + treeNodes.add(treeNode); + } + rootNode.setChildren(treeNodes); + treeView.refreshTreeView(); + } + + @Override + public void refreshTree() { + treeView.refreshTreeView(); + } +} + + diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/SettingsActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java similarity index 93% rename from app/src/main/java/ru/volgorobot/vrcatalog/SettingsActivity.java rename to app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java index d74d8a9..e4d5335 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/SettingsActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java @@ -1,8 +1,10 @@ -package ru.volgorobot.vrcatalog; +package ru.volgorobot.vrcatalog.view; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; + +import ru.volgorobot.vrcatalog.R; import ru.volgorobot.vrcatalog.additional.AppCompatPreferenceActivity; public class SettingsActivity extends AppCompatPreferenceActivity { diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 4bc0a9c..f89d895 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - tools:context=".AboutActivity"> + tools:context=".view.AboutActivity"> + tools:context=".view.MainActivity">