From 0ea2b24c608e8319499f4d1eda5abf10f10e1edd Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Tue, 26 Feb 2019 09:27:51 +0800 Subject: [PATCH] Add two features: refresh searching and searching in SearchActivity. Fixed a bug which is the listener object is null when it is called because the parse failed in ParsePost, ParseSubredditData and ParseUserData. --- .idea/misc.xml | 12 +- .../infinityforreddit/MainActivity.java | 2 - .../infinityforreddit/ParsePost.java | 7 +- .../infinityforreddit/ParseSubredditData.java | 1 - .../infinityforreddit/ParseUserData.java | 40 ++--- .../infinityforreddit/SearchActivity.java | 141 +++++++++++++++++- .../SubredditListingDataSourceFactory.java | 2 +- .../SubredditListingFragment.java | 13 +- .../UserListingDataSourceFactory.java | 16 +- .../UserListingFragment.java | 9 +- .../ViewUserDetailActivity.java | 36 ----- app/src/main/res/layout/activity_search.xml | 38 ++++- app/src/main/res/values/strings.xml | 2 + 13 files changed, 223 insertions(+), 96 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 3386629a..be2c23c1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -2,10 +2,10 @@ diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java index 7448daf9..4557e50c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java @@ -75,8 +75,6 @@ public class MainActivity extends AppCompatActivity { private boolean mFetchUserInfoSuccess; private boolean mInsertSuccess; - private FragmentCommunicator mFragmentCommunicator; - private SubscribedSubredditViewModel mSubscribedSubredditViewModel; private SubscribedUserViewModel mSubscribedUserViewModel; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java index 5d865ebd..4e0b574b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java @@ -37,19 +37,24 @@ class ParsePost { ParsePostDataAsyncTask(String response, Locale locale, ParsePostListener parsePostListener) { + this.parsePostListener = parsePostListener; try { jsonResponse = new JSONObject(response); this.locale = locale; - this.parsePostListener = parsePostListener; newPosts = new ArrayList<>(); parseFailed = false; } catch (JSONException e) { e.printStackTrace(); + parseFailed = true; } } @Override protected Void doInBackground(Void... voids) { + if(parseFailed) { + return null; + } + try { JSONArray allData = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java index e12da13f..6501b709 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java @@ -116,7 +116,6 @@ class ParseSubredditData { } catch (JSONException e) { Log.i("subreddit json error", e.getMessage()); parseFailed = true; - parseSubredditListingDataListener.onParseSubredditListingDataFail(); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java index 618a9a81..f52441b8 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java @@ -52,24 +52,6 @@ public class ParseUserData { protected Void doInBackground(Void... voids) { try { userData = parseUserDataBase(jsonResponse); - /*jsonResponse = jsonResponse.getJSONObject(JSONUtils.DATA_KEY); - String userName = jsonResponse.getString(JSONUtils.NAME_KEY); - String iconImageUrl = jsonResponse.getString(JSONUtils.ICON_IMG_KEY); - String bannerImageUrl = ""; - boolean canBeFollowed; - if(jsonResponse.has(JSONUtils.SUBREDDIT_KEY) && !jsonResponse.isNull(JSONUtils.SUBREDDIT_KEY)) { - bannerImageUrl = jsonResponse.getJSONObject(JSONUtils.SUBREDDIT_KEY).getString(JSONUtils.BANNER_IMG_KEY); - canBeFollowed = true; - } else { - canBeFollowed = false; - } - int linkKarma = jsonResponse.getInt(JSONUtils.LINK_KARMA_KEY); - int commentKarma = jsonResponse.getInt(JSONUtils.COMMENT_KARMA_KEY); - int karma = linkKarma + commentKarma; - boolean isGold = jsonResponse.getBoolean(JSONUtils.IS_GOLD_KEY); - boolean isFriend = jsonResponse.getBoolean(JSONUtils.IS_FRIEND_KEY); - - userData = new UserData(userName, iconImageUrl, bannerImageUrl, karma, isGold, isFriend, canBeFollowed);*/ } catch (JSONException e) { parseFailed = true; Log.i("parse user data error", e.getMessage()); @@ -88,6 +70,7 @@ public class ParseUserData { } private static class ParseUserListingDataAsyncTask extends AsyncTask { + private String response; private JSONObject jsonResponse; private ParseUserListingDataListener parseUserListingDataListener; private String after; @@ -96,24 +79,27 @@ public class ParseUserData { private ArrayList userDataArrayList; ParseUserListingDataAsyncTask(String response, ParseUserListingDataListener parseUserListingDataListener){ + this.parseUserListingDataListener = parseUserListingDataListener; + this.response = response; try { jsonResponse = new JSONObject(response); - this.parseUserListingDataListener = parseUserListingDataListener; parseFailed = false; userDataArrayList = new ArrayList<>(); } catch (JSONException e) { Log.i("userdata json error", e.getMessage()); - this.parseUserListingDataListener.onParseUserListingDataFailed(); + parseFailed = true; } } @Override protected Void doInBackground(Void... voids) { try { - after = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); - JSONArray children = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - for(int i = 0; i < children.length(); i++) { - userDataArrayList.add(parseUserDataBase(children.getJSONObject(i))); + if(!parseFailed) { + after = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); + JSONArray children = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + for(int i = 0; i < children.length(); i++) { + userDataArrayList.add(parseUserDataBase(children.getJSONObject(i))); + } } } catch (JSONException e) { parseFailed = true; @@ -127,7 +113,11 @@ public class ParseUserData { if(!parseFailed) { parseUserListingDataListener.onParseUserListingDataSuccess(userDataArrayList, after); } else { - parseUserListingDataListener.onParseUserListingDataFailed(); + if(response.equals("\"{}\"")) { + parseUserListingDataListener.onParseUserListingDataSuccess(new ArrayList<>(), null); + } else { + parseUserListingDataListener.onParseUserListingDataFailed(); + } } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java index 25a78b9d..51244e44 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java @@ -2,37 +2,97 @@ package ml.docilealligator.infinityforreddit; import android.content.Intent; import android.os.Bundle; +import android.view.Menu; import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import com.ferfalk.simplesearchview.SimpleSearchView; import com.google.android.material.tabs.TabLayout; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; +import butterknife.BindView; +import butterknife.ButterKnife; public class SearchActivity extends AppCompatActivity { static final String QUERY_KEY = "QK"; private String mQuery; + + @BindView(R.id.toolbar_search_activity) Toolbar toolbar; + @BindView(R.id.search_view_search_activity) SimpleSearchView simpleSearchView; + @BindView(R.id.tab_layout_search_activity) TabLayout tabLayout; + @BindView(R.id.transparent_overlay_search_activity) View transparentOverlay; + @BindView(R.id.view_pager_search_activity) ViewPager viewPager; + + private SectionsPagerAdapter sectionsPagerAdapter; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search); + ButterKnife.bind(this); - Toolbar toolbar = findViewById(R.id.toolbar_search_activity); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - ViewPager viewPager = findViewById(R.id.view_pager_search_activity); - PagerAdapter pagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - viewPager.setAdapter(pagerAdapter); - TabLayout tabLayout = findViewById(R.id.tab_layout_search_activity); + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(2); tabLayout.setupWithViewPager(viewPager); + transparentOverlay.setOnClickListener(view -> simpleSearchView.onBackPressed()); + + simpleSearchView.setOnQueryTextListener(new SimpleSearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + Intent intent = getIntent(); + intent.putExtra(SearchActivity.QUERY_KEY, query); + finish(); + startActivity(intent); + overridePendingTransition(0, 0); + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + return false; + } + + @Override + public boolean onQueryTextCleared() { + return false; + } + }); + + simpleSearchView.setOnSearchViewListener(new SimpleSearchView.SearchViewListener() { + @Override + public void onSearchViewShown() { + transparentOverlay.setVisibility(View.VISIBLE); + } + + @Override + public void onSearchViewClosed() { + transparentOverlay.setVisibility(View.GONE); + } + + @Override + public void onSearchViewShownAnimation() { + + } + + @Override + public void onSearchViewClosedAnimation() { + + } + }); + // Get the intent, verify the action and get the query Intent intent = getIntent(); String query = intent.getExtras().getString(QUERY_KEY); @@ -42,22 +102,55 @@ public class SearchActivity extends AppCompatActivity { } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (simpleSearchView.onActivityResult(requestCode, resultCode, data)) { + return; + } + + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main_activity, menu); + + simpleSearchView.setMenuItem(menu.findItem(R.id.action_search_main_activity)); + + return true; + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; + case R.id.action_refresh_main_activity: + sectionsPagerAdapter.refresh(); + return true; } return super.onOptionsItemSelected(item); } + @Override + public void onBackPressed() { + if (simpleSearchView.onBackPressed()) { + return; + } + super.onBackPressed(); + } + public class SectionsPagerAdapter extends FragmentPagerAdapter { + private PostFragment postFragment; + private SubredditListingFragment subredditListingFragment; + private UserListingFragment userListingFragment; public SectionsPagerAdapter(FragmentManager fm) { super(fm); } + @NonNull @Override public Fragment getItem(int position) { switch (position) { @@ -104,5 +197,41 @@ public class SearchActivity extends AppCompatActivity { } return null; } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Fragment fragment = (Fragment) super.instantiateItem(container, position); + switch (position) { + case 0: + postFragment = (PostFragment) fragment; + break; + case 1: + subredditListingFragment = (SubredditListingFragment) fragment; + break; + case 2: + userListingFragment = (UserListingFragment) fragment; + break; + } + return fragment; + } + + public void refresh() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).refresh(); + } + if(subredditListingFragment != null) { + ((FragmentCommunicator) subredditListingFragment).refresh(); + } + if (userListingFragment != null) { + ((FragmentCommunicator) userListingFragment).refresh(); + } + } + + public void newSearch() { + getItem(0); + getItem(1); + getItem(2); + } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java index 168fadbd..bc64c052 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java @@ -24,7 +24,7 @@ public class SubredditListingDataSourceFactory extends DataSource.Factory { @NonNull @Override public DataSource create() { - SubredditListingDataSource subredditListingDataSource = new SubredditListingDataSource(retrofit, + subredditListingDataSource = new SubredditListingDataSource(retrofit, query, onSubredditListingDataFetchedCallback); subredditListingDataSourceMutableLiveData.postValue(subredditListingDataSource); return subredditListingDataSource; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java index f591c4f9..c109d767 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java @@ -1,7 +1,6 @@ package ml.docilealligator.infinityforreddit; -import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.view.LayoutInflater; @@ -31,7 +30,7 @@ import retrofit2.Retrofit; /** * A simple {@link Fragment} subclass. */ -public class SubredditListingFragment extends Fragment { +public class SubredditListingFragment extends Fragment implements FragmentCommunicator { static final String QUERY_KEY = "QK"; @@ -79,9 +78,6 @@ public class SubredditListingFragment extends Fragment { mQuery = getArguments().getString(QUERY_KEY); - String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE) - .getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, ""); - SubredditListingViewModel.Factory factory = new SubredditListingViewModel.Factory(mRetrofit, mQuery, new SubredditListingDataSource.OnSubredditListingDataFetchedCallback() { @Override @@ -116,7 +112,7 @@ public class SubredditListingFragment extends Fragment { mProgressBar.setVisibility(View.GONE); } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { mFetchSubredditListingInfoLinearLayout.setOnClickListener(view -> mSubredditListingViewModel.retry()); - showErrorView(R.string.load_posts_error); + showErrorView(R.string.search_subreddits_error); } else { mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE); mProgressBar.setVisibility(View.VISIBLE); @@ -138,4 +134,9 @@ public class SubredditListingFragment extends Fragment { Glide.with(this).load(R.drawable.load_post_error_indicator).into(mFetchSubredditListingInfoImageView); } } + + @Override + public void refresh() { + mSubredditListingViewModel.refresh(); + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingDataSourceFactory.java index 6498412c..99e1fcfb 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingDataSourceFactory.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingDataSourceFactory.java @@ -10,31 +10,31 @@ public class UserListingDataSourceFactory extends DataSource.Factory { private String query; private UserListingDataSource.OnUserListingDataFetchedCallback onUserListingDataFetchedCallback; - private UserListingDataSource UserListingDataSource; - private MutableLiveData UserListingDataSourceMutableLiveData; + private UserListingDataSource userListingDataSource; + private MutableLiveData userListingDataSourceMutableLiveData; UserListingDataSourceFactory(Retrofit retrofit, String query, UserListingDataSource.OnUserListingDataFetchedCallback onUserListingDataFetchedCallback) { this.retrofit = retrofit; this.query = query; this.onUserListingDataFetchedCallback = onUserListingDataFetchedCallback; - UserListingDataSourceMutableLiveData = new MutableLiveData<>(); + userListingDataSourceMutableLiveData = new MutableLiveData<>(); } @NonNull @Override public DataSource create() { - UserListingDataSource UserListingDataSource = new UserListingDataSource(retrofit, + userListingDataSource = new UserListingDataSource(retrofit, query, onUserListingDataFetchedCallback); - UserListingDataSourceMutableLiveData.postValue(UserListingDataSource); - return UserListingDataSource; + userListingDataSourceMutableLiveData.postValue(userListingDataSource); + return userListingDataSource; } public MutableLiveData getUserListingDataSourceMutableLiveData() { - return UserListingDataSourceMutableLiveData; + return userListingDataSourceMutableLiveData; } UserListingDataSource getUserListingDataSource() { - return UserListingDataSource; + return userListingDataSource; } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java index abc9dcdb..832b5140 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java @@ -31,7 +31,7 @@ import retrofit2.Retrofit; /** * A simple {@link Fragment} subclass. */ -public class UserListingFragment extends Fragment { +public class UserListingFragment extends Fragment implements FragmentCommunicator { static final String QUERY_KEY = "QK"; @BindView(R.id.coordinator_layout_user_listing_fragment) @@ -122,7 +122,7 @@ public class UserListingFragment extends Fragment { mProgressBar.setVisibility(View.GONE); } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { mFetchUserListingInfoLinearLayout.setOnClickListener(view -> mUserListingViewModel.retry()); - showErrorView(R.string.load_posts_error); + showErrorView(R.string.search_users_error); } else { mFetchUserListingInfoLinearLayout.setVisibility(View.GONE); mProgressBar.setVisibility(View.VISIBLE); @@ -144,4 +144,9 @@ public class UserListingFragment extends Fragment { Glide.with(this).load(R.drawable.load_post_error_indicator).into(mFetchUserListingInfoImageView); } } + + @Override + public void refresh() { + mUserListingViewModel.refresh(); + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java index eacca302..c548043a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java @@ -293,40 +293,4 @@ public class ViewUserDetailActivity extends AppCompatActivity { return null; } } - - /*private static class CheckIsFollowingUserAsyncTask extends AsyncTask { - - private SubscribedUserDao subscribedUserDao; - private String userName; - private SubscribedUserData subscribedUserData; - private CheckIsFollowingUserListener checkIsFollowingUserListener; - - interface CheckIsFollowingUserListener { - void isSubscribed(); - void isNotSubscribed(); - } - - CheckIsFollowingUserAsyncTask(SubscribedUserDao subscribedUserDao, String userName, - CheckIsFollowingUserListener checkIsFollowingUserListener) { - this.subscribedUserDao = subscribedUserDao; - this.userName = userName; - this.checkIsFollowingUserListener = checkIsFollowingUserListener; - } - - @Override - protected Void doInBackground(Void... voids) { - subscribedUserData = subscribedUserDao.getSubscribedUser(userName); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if(subscribedUserData != null) { - checkIsFollowingUserListener.isSubscribed(); - } else { - checkIsFollowingUserListener.isNotSubscribed(); - } - } - }*/ } diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml index 8d080b46..f6ff281f 100644 --- a/app/src/main/res/layout/activity_search.xml +++ b/app/src/main/res/layout/activity_search.xml @@ -11,12 +11,32 @@ android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> - + android:layout_height="wrap_content"> + + + + + + + + Error loading image. Tap to retry. Error loading posts.\nTap to retry. + Error searching subreddits.\nTap to retry. + Error searching users.\nTap to retry. No posts found. No subreddits found. No users found.