From bdea6547b14208ff2d7366bd45103b205b5cd197 Mon Sep 17 00:00:00 2001 From: dsukmanova Date: Sat, 16 Jul 2016 22:00:14 +0300 Subject: [PATCH 01/24] Task1(part 1). Delete DetailsActivity and make fragments (main and details) --- Singers/app/src/main/AndroidManifest.xml | 5 - ...ailsActivity.java => DetailsFragment.java} | 61 ++++---- .../java/ru/daria/singers/HomeFragment.java | 131 ++++++++++++++++++ .../ru/daria/singers/ListItemAdapter.java | 9 +- .../java/ru/daria/singers/MainActivity.java | 83 +++++------ .../java/ru/daria/singers/MainFragment.java | 78 +++++++++++ .../main/java/ru/daria/singers/Singer.java | 1 - .../app/src/main/res/layout/activity_main.xml | 8 +- Singers/app/src/main/res/layout/details.xml | 11 +- .../app/src/main/res/menu/options_menu.xml | 7 +- 10 files changed, 300 insertions(+), 94 deletions(-) rename Singers/app/src/main/java/ru/daria/singers/{DetailsActivity.java => DetailsFragment.java} (61%) create mode 100644 Singers/app/src/main/java/ru/daria/singers/HomeFragment.java create mode 100644 Singers/app/src/main/java/ru/daria/singers/MainFragment.java diff --git a/Singers/app/src/main/AndroidManifest.xml b/Singers/app/src/main/AndroidManifest.xml index 1d2d0f1..9b5719b 100644 --- a/Singers/app/src/main/AndroidManifest.xml +++ b/Singers/app/src/main/AndroidManifest.xml @@ -26,11 +26,6 @@ android:name="android.app.searchable" android:resource="@xml/searchable" /> - - diff --git a/Singers/app/src/main/java/ru/daria/singers/DetailsActivity.java b/Singers/app/src/main/java/ru/daria/singers/DetailsFragment.java similarity index 61% rename from Singers/app/src/main/java/ru/daria/singers/DetailsActivity.java rename to Singers/app/src/main/java/ru/daria/singers/DetailsFragment.java index 89bf338..7cb5332 100644 --- a/Singers/app/src/main/java/ru/daria/singers/DetailsActivity.java +++ b/Singers/app/src/main/java/ru/daria/singers/DetailsFragment.java @@ -1,12 +1,12 @@ package ru.daria.singers; -import android.content.Intent; +import android.app.Fragment; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; -import android.view.Menu; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; @@ -14,45 +14,53 @@ import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; -public class DetailsActivity extends AppCompatActivity { - //настройка кэширования изображений +/** + * Created by dsukmanova on 16.07.16. + */ +public class DetailsFragment extends Fragment { private static DisplayImageOptions options = new DisplayImageOptions.Builder(). cacheInMemory(true).cacheOnDisk(true).build(); - private String albumsDescr; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.details); + } + + @Override + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.details, container, false); + final MainActivity activity = (MainActivity)getActivity(); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + Toolbar toolbar = (Toolbar) activity.findViewById(R.id.toolbar); toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha); + activity.showMenuVisible(toolbar.getMenu(), false); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //действие аналогично стандартной кнопке "Назад" - onBackPressed(); + activity.onBackPressed(); } }); - ImageView image = (ImageView) findViewById(R.id.image); - TextView description = (TextView) findViewById(R.id.descriprion); - TextView genres = (TextView) findViewById(R.id.genres); - TextView albums = (TextView) findViewById(R.id.albums); + ImageView image = (ImageView) view.findViewById(R.id.image); + TextView description = (TextView) view.findViewById(R.id.descriprion); + TextView genres = (TextView) view.findViewById(R.id.genres); + TextView albums = (TextView) view.findViewById(R.id.albums); //получаем экземпляр Singer из MainActivity - Intent intent = getIntent(); - Bundle b = intent.getExtras(); + Bundle b = getArguments(); Singer singer = (Singer) b.get("SINGER"); toolbar.setTitle(singer.getName()); //пока подгружается изображение показываем стандартное String uri = "@drawable/defaultimage"; - int imageResource = getResources().getIdentifier(uri, null, getPackageName()); + int imageResource = getResources().getIdentifier(uri, null, activity.getPackageName()); Drawable res = getResources().getDrawable(imageResource); image.setImageDrawable(res); //Конфигурация для ImageLoader - ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build(); + ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(activity).build(); final ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.init(config); @@ -63,20 +71,13 @@ public void onClick(View v) { description.setText(singer.getDescription()); genres.setText(singer.genresToString()); int albumsNum = singer.getAlbums(); - String[] albumCases = {"альбом", "альбома", "альбомов"}; int tracksNum = singer.getTracks(); - String[] trackCases = {"песня", "песни", "песен"}; //склоняем альбомы и песни - String albumsDescr = "%d %s • %d %s"; - albumsDescr = String.format(albumsDescr, albumsNum, singer.getEnding(albumsNum, albumCases), - tracksNum, singer.getEnding(tracksNum, trackCases)); + String albumsDescr = "%s • %s"; + albumsDescr = String.format(albumsDescr, + getResources().getQuantityString(R.plurals.songs, albumsNum, albumsNum), + getResources().getQuantityString(R.plurals.tracks, tracksNum, tracksNum)); albums.setText(albumsDescr); - + return view; } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - return super.onCreateOptionsMenu(menu); - } - } diff --git a/Singers/app/src/main/java/ru/daria/singers/HomeFragment.java b/Singers/app/src/main/java/ru/daria/singers/HomeFragment.java new file mode 100644 index 0000000..8c64fbe --- /dev/null +++ b/Singers/app/src/main/java/ru/daria/singers/HomeFragment.java @@ -0,0 +1,131 @@ +package ru.daria.singers; + +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by dsukmanova on 16.07.16. + */ +public class HomeFragment extends Fragment { + List singers = new ArrayList(); + View view; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + + view = inflater.inflate(R.layout.splash, container, false); + Extractor ex = new Extractor(new Extractor.AsyncResponse() { + @Override + public void processFinish(String output) { + try { + JSONArray dataJson = new JSONArray(output); + singers = getSingersFromJson(dataJson); + Bundle arg = new Bundle(); + arg.putSerializable("SINGERS", (Serializable) singers); + MainFragment fragment = new MainFragment(); + fragment.setArguments(arg); + + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fragmentContainer, fragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + } catch (JSONException ex) { + ex.printStackTrace(); + Button b = (Button) view.findViewById(R.id.tryAgainButton); + b.setVisibility(View.VISIBLE); + TextView v = (TextView) view.findViewById(R.id.splashText); + v.setText("Невозможно загрузить список исполнителей."); + } + } + }); + ex.execute(); + return view; + } + + public void buttonOnClick(View view) { + Button b = (Button) view.findViewById(R.id.tryAgainButton); + b.setVisibility(View.INVISIBLE); + + } + + /** + * Функция создает список исполнителей по входному json + * + * @param jSingers JSONArray Массив исполнителей в формате json + */ + public List getSingersFromJson(JSONArray jSingers) { + List singers = new ArrayList<>(); + for (int i = 0; i < jSingers.length(); i++) { + try { + JSONObject jSinger = jSingers.getJSONObject(i); + Long id = null; + if (jSinger.has("id")) id = jSinger.getLong("id"); + String name = ""; + if (jSinger.has("name")) name = jSinger.getString("name"); + List genres = new ArrayList<>(); + if (jSinger.has("genres")) { + JSONArray jGenres = jSinger.getJSONArray("genres"); + for (int j = 0; j < jGenres.length(); j++) { + genres.add(jGenres.getString(j)); + } + } + int tracks = 0; + if (jSinger.has("tracks")) tracks = jSinger.getInt("tracks"); + int albums = 0; + if (jSinger.has("albums")) albums = jSinger.getInt("albums"); + String link = ""; + if (jSinger.has("link")) link = jSinger.getString("link"); + String description = ""; + if (jSinger.has("description")) { + description = jSinger.getString("description"); + //описание будет всегда с заглавной буквы + if (description.length() > 0) { + description = description.substring(0, 1).toUpperCase() + description.substring(1); + } + } + + Map covers = new LinkedHashMap<>(); + if (jSinger.has("cover")) { + JSONObject jCovers = jSinger.getJSONObject("cover"); + String small = jCovers.getString("small"); + String big = jCovers.getString("big"); + if (small != null) covers.put(Singer.coverTypes.small, small); + if (big != null) covers.put(Singer.coverTypes.big, big); + } + Singer singer = new Singer(id, name, genres, tracks, albums, link, description, covers); + singers.add(singer); + } catch (JSONException ex) { + Log.e("ERROR", String.format("getJSONObject(%d) occurred an error", i)); + } + } + return singers; + } + +} diff --git a/Singers/app/src/main/java/ru/daria/singers/ListItemAdapter.java b/Singers/app/src/main/java/ru/daria/singers/ListItemAdapter.java index 3357517..5fd33d0 100644 --- a/Singers/app/src/main/java/ru/daria/singers/ListItemAdapter.java +++ b/Singers/app/src/main/java/ru/daria/singers/ListItemAdapter.java @@ -18,6 +18,7 @@ import java.util.List; public class ListItemAdapter extends BaseAdapter implements Filterable { + private Context context; private final ImageLoader imageLoader; private LayoutInflater lInflater; private List singers; @@ -40,6 +41,7 @@ public ListItemAdapter(Activity context, ImageLoader imageLoader, View.OnClickListener callback ) { + this.context = context; this.singers = singers; this.filteredSingers = singers; this.imageLoader = imageLoader; @@ -102,9 +104,10 @@ public View getView(int position, View convertView, ViewGroup parent) { String[] trackCases = {"песня", "песни", "песен"}; //склоняем альбомы и песни - String albumsDescr = "%d %s • %d %s"; - albumsDescr = String.format(albumsDescr, albumsNum, singer.getEnding(albumsNum, albumCases), - tracksNum, singer.getEnding(tracksNum, trackCases)); + String albumsDescr = "%s • %s"; + albumsDescr = String.format(albumsDescr, + context.getResources().getQuantityString(R.plurals.songs,albumsNum,albumsNum), + context.getResources().getQuantityString(R.plurals.tracks, tracksNum, tracksNum)); holder.description.setText(albumsDescr); return view; } diff --git a/Singers/app/src/main/java/ru/daria/singers/MainActivity.java b/Singers/app/src/main/java/ru/daria/singers/MainActivity.java index 707c792..47c9554 100644 --- a/Singers/app/src/main/java/ru/daria/singers/MainActivity.java +++ b/Singers/app/src/main/java/ru/daria/singers/MainActivity.java @@ -1,9 +1,10 @@ package ru.daria.singers; +import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.os.Bundle; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.AppCompatActivity; @@ -11,56 +12,29 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; -import android.widget.ListView; import android.support.v7.widget.SearchView; -import com.nhaarman.listviewanimations.appearance.simple.SwingRightInAnimationAdapter; -import com.nostra13.universalimageloader.core.*; - import java.util.ArrayList; import java.util.List; -public class MainActivity extends AppCompatActivity implements View.OnClickListener { +public class MainActivity extends AppCompatActivity implements MainFragment.OnSingerSelectedListener { List singers = new ArrayList<>(); - ListItemAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - // Конфигурация для ImageLoader - ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build(); - final ImageLoader imageLoader = ImageLoader.getInstance(); - imageLoader.init(config); - setContentView(R.layout.activity_main); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - Intent intent = getIntent(); - //получаем список исполнителей из HomeActivity - singers = (List) intent.getSerializableExtra("SINGERS"); - adapter = new ListItemAdapter(MainActivity.this, singers, imageLoader, MainActivity.this); - - //анимация при пролистывании списка исполнителей - final SwingRightInAnimationAdapter rightInAnimationAdapter = new SwingRightInAnimationAdapter(adapter); - - ListView mainList = (ListView) findViewById(R.id.listView); - rightInAnimationAdapter.setAbsListView(mainList); - mainList.setAdapter(rightInAnimationAdapter); - mainList.setTextFilterEnabled(true); + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + MainFragment fragment = new MainFragment(); + fragmentTransaction.add(R.id.fragmentContainer, fragment); + fragmentTransaction.commit(); } - //Действие по нажатию строки в ListView с исполнителями - @Override - public void onClick(View view) { - int position = ((ListView) view.getParent()).getPositionForView(view); - Singer singer = adapter.getSinger(position); - Intent info = new Intent(this, DetailsActivity.class); - info.putExtra("SINGER", singer); - startActivity(info); + private ListItemAdapter getListAdapter() { + MainFragment currFragment = (MainFragment) getFragmentManager().findFragmentById(R.id.fragmentContainer); + return currFragment.adapter; } @Override @@ -81,14 +55,14 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onQueryTextSubmit(String query) { //при подтверждении текста поиска - adapter.getFilter().filter(query); + getListAdapter().getFilter().filter(query); return true; } @Override public boolean onQueryTextChange(String newText) { //при изменении текста поиска - adapter.getFilter().filter(newText); + getListAdapter().getFilter().filter(newText); return true; } }; @@ -96,9 +70,40 @@ public boolean onQueryTextChange(String newText) { return super.onCreateOptionsMenu(menu); } + public void showMenuVisible (Menu menu, boolean showMenu){ + if(menu == null) return; + menu.setGroupVisible(R.id.main_menu_group, showMenu); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } + @Override + public void onBackPressed() { + if (getFragmentManager().getBackStackEntryCount() == 0) { + this.finish(); + } else { + getFragmentManager().popBackStack(); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + toolbar.setNavigationIcon(null); + toolbar.setTitle(R.string.app_name); + showMenuVisible(toolbar.getMenu(), true); + } + } + + @Override + public void onSingerSelected(Singer singer) { + DetailsFragment fragment = new DetailsFragment(); + Bundle arg = new Bundle(); + arg.putSerializable("SINGER", singer); + fragment.setArguments(arg); + + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fragmentContainer, fragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + } } \ No newline at end of file diff --git a/Singers/app/src/main/java/ru/daria/singers/MainFragment.java b/Singers/app/src/main/java/ru/daria/singers/MainFragment.java new file mode 100644 index 0000000..2082371 --- /dev/null +++ b/Singers/app/src/main/java/ru/daria/singers/MainFragment.java @@ -0,0 +1,78 @@ +package ru.daria.singers; + +import android.app.Activity; +import android.app.Fragment; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import com.nhaarman.listviewanimations.appearance.simple.SwingRightInAnimationAdapter; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by dsukmanova on 15.07.16. + */ +public class MainFragment extends Fragment implements View.OnClickListener { + List singers = new ArrayList<>(); + ListItemAdapter adapter; + OnSingerSelectedListener mListener; + + public interface OnSingerSelectedListener { + void onSingerSelected(Singer singer); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + mListener = (OnSingerSelectedListener) getActivity(); + } catch (ClassCastException ex) { + throw new ClassCastException(getActivity().toString() + "must implement OnSingerSelectedListener"); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.content_main, container, false); + Activity activity = getActivity(); + + Toolbar toolbar = (Toolbar) activity.findViewById(R.id.toolbar); + + ((AppCompatActivity) activity).setSupportActionBar(toolbar); + + // Конфигурация для ImageLoader + ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity()).build(); + final ImageLoader imageLoader = ImageLoader.getInstance(); + imageLoader.init(config); + + //получаем список исполнителей из HomeActivity + singers = (List) activity.getIntent().getSerializableExtra("SINGERS"); + + adapter = new ListItemAdapter(activity, singers, imageLoader, this); + final SwingRightInAnimationAdapter rightInAnimationAdapter = new SwingRightInAnimationAdapter(adapter); + + ListView mainList = (ListView) view.findViewById(R.id.listView); + rightInAnimationAdapter.setAbsListView(mainList); + mainList.setAdapter(rightInAnimationAdapter); + mainList.setTextFilterEnabled(true); + + return view; + } + + @Override + public void onClick(View view) { + int position = ((ListView) view.getParent()).getPositionForView(view); + Singer singer = adapter.getSinger(position); + mListener.onSingerSelected(singer); + } +} diff --git a/Singers/app/src/main/java/ru/daria/singers/Singer.java b/Singers/app/src/main/java/ru/daria/singers/Singer.java index ca8efa6..a98b3a6 100644 --- a/Singers/app/src/main/java/ru/daria/singers/Singer.java +++ b/Singers/app/src/main/java/ru/daria/singers/Singer.java @@ -1,7 +1,6 @@ package ru.daria.singers; import java.io.Serializable; -import java.util.IllegalFormatException; import java.util.List; import java.util.Map; diff --git a/Singers/app/src/main/res/layout/activity_main.xml b/Singers/app/src/main/res/layout/activity_main.xml index 4d3a1e9..3d94336 100644 --- a/Singers/app/src/main/res/layout/activity_main.xml +++ b/Singers/app/src/main/res/layout/activity_main.xml @@ -16,6 +16,12 @@ layout="@layout/toolbar" /> - + + + diff --git a/Singers/app/src/main/res/layout/details.xml b/Singers/app/src/main/res/layout/details.xml index 0875fdd..6c210f8 100644 --- a/Singers/app/src/main/res/layout/details.xml +++ b/Singers/app/src/main/res/layout/details.xml @@ -7,19 +7,10 @@ android:fitsSystemWindows="true" tools:context="ru.daria.singers.MainActivity"> - - - - - - + + From 429bf646429c50b76d7b09adae40fce11e9caf99 Mon Sep 17 00:00:00 2001 From: dsukmanova Date: Sat, 16 Jul 2016 22:12:29 +0300 Subject: [PATCH 02/24] Fix plurals (add plurals resource) --- .../main/java/ru/daria/singers/Singer.java | 34 ------------------- Singers/app/src/main/res/values/plurals.xml | 19 +++++++++++ 2 files changed, 19 insertions(+), 34 deletions(-) create mode 100644 Singers/app/src/main/res/values/plurals.xml diff --git a/Singers/app/src/main/java/ru/daria/singers/Singer.java b/Singers/app/src/main/java/ru/daria/singers/Singer.java index a98b3a6..3b63cf2 100644 --- a/Singers/app/src/main/java/ru/daria/singers/Singer.java +++ b/Singers/app/src/main/java/ru/daria/singers/Singer.java @@ -112,38 +112,4 @@ public String genresToString() { public String toString() { return name.toString(); } - - /** - * Функция возвращает окончание для множественного числа слова на основании числа и массива окончаний - * - * @param number int Число на основе которого нужно сформировать окончание - * @param endingArray Array Массив слов или окончаний для чисел (1, 4, 5), - * например array('песня', 'песни', 'песен') - * @return String - */ - public String getEnding(int number, String[] endingArray) { - if (endingArray.length != 3) - throw new ArrayIndexOutOfBoundsException("Out of bounds exception. Array must contains 3 elements!"); - number = number % 100; - String ending = ""; - if (number >= 11 && number <= 19) { - ending = endingArray[2]; - } else { - int i = number % 10; - switch (i) { - case (1): - ending = endingArray[0]; - break; - case (2): - case (3): - case (4): - ending = endingArray[1]; - break; - default: - ending = endingArray[2]; - } - } - return ending; - } - } diff --git a/Singers/app/src/main/res/values/plurals.xml b/Singers/app/src/main/res/values/plurals.xml new file mode 100644 index 0000000..1b58546 --- /dev/null +++ b/Singers/app/src/main/res/values/plurals.xml @@ -0,0 +1,19 @@ + + + + нет песен + %1$d песня + %1$d песни + %1$d песни + %1$d песен + %1$d песен + + + нет альбомов + %1$d альбом + %1$d альбома + %1$d альбома + %1$d альбомов + %1$d альбомов + + \ No newline at end of file From 2e85591596527f83de19d71e0fead313d924f535 Mon Sep 17 00:00:00 2001 From: dsukmanova Date: Sun, 17 Jul 2016 16:20:57 +0300 Subject: [PATCH 03/24] Add dataLoader for loading json, remove HomeFragment for a while --- .../java/ru/daria/singers/DataLoader.java | 104 ++++++++++++++ .../main/java/ru/daria/singers/Extractor.java | 72 ---------- .../java/ru/daria/singers/HomeActivity.java | 60 +++++--- .../java/ru/daria/singers/HomeFragment.java | 131 ------------------ 4 files changed, 142 insertions(+), 225 deletions(-) create mode 100644 Singers/app/src/main/java/ru/daria/singers/DataLoader.java delete mode 100644 Singers/app/src/main/java/ru/daria/singers/Extractor.java delete mode 100644 Singers/app/src/main/java/ru/daria/singers/HomeFragment.java diff --git a/Singers/app/src/main/java/ru/daria/singers/DataLoader.java b/Singers/app/src/main/java/ru/daria/singers/DataLoader.java new file mode 100644 index 0000000..e643e4f --- /dev/null +++ b/Singers/app/src/main/java/ru/daria/singers/DataLoader.java @@ -0,0 +1,104 @@ +package ru.daria.singers; + +import android.content.Context; +import android.content.Loader; +import android.os.AsyncTask; +import android.util.Log; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Created by dsukmanova on 17.07.16. + */ +public class DataLoader extends Loader { + ExtractorNew extractor; + + public DataLoader(Context context) { + super(context); + } + + @Override + protected void onStartLoading() { + super.onStartLoading(); + } + + @Override + protected void onStopLoading() { + super.onStopLoading(); + } + + @Override + protected void onForceLoad() { + super.onForceLoad(); + if (extractor != null) + extractor.cancel(true); + extractor = new ExtractorNew(); + extractor.execute(); + } + + @Override + protected void onAbandon() { + super.onAbandon(); + } + + @Override + protected void onReset() { + super.onReset(); + } + + + class ExtractorNew extends AsyncTask { + private final String URLSingers = "http://cache-default06g.cdn.yandex.net/download.cdn.yandex.net/mobilization-2016/artists.json"; + private HttpURLConnection urlConnection = null; + private String resultJson = ""; + + public ExtractorNew() { + } + + public void getResultFromTask(String result) { + deliverResult(result); + } + + @Override + protected String doInBackground(Void... params) { + // получаем данные с внешнего ресурса + try { + URL url = new URL(URLSingers); + urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.setRequestMethod("GET"); + urlConnection.connect(); + + InputStream inputStream = urlConnection.getInputStream(); + StringBuilder buffer = new StringBuilder(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String line; + while ((line = reader.readLine()) != null) { + buffer.append(line); + } + + resultJson = buffer.toString(); + } catch (MalformedURLException e) { + Log.e("ERROR", "URL is not available"); + } catch (IOException ex) { + Log.e("ERROR", "Cannot open url connection."); + } finally { + if (urlConnection != null) { + urlConnection.disconnect(); + } + } + return resultJson; + } + + @Override + protected void onPostExecute(String strJson) { + super.onPostExecute(strJson); + getResultFromTask(strJson); + } + } +} diff --git a/Singers/app/src/main/java/ru/daria/singers/Extractor.java b/Singers/app/src/main/java/ru/daria/singers/Extractor.java deleted file mode 100644 index 84b4d71..0000000 --- a/Singers/app/src/main/java/ru/daria/singers/Extractor.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.daria.singers; - -import android.os.AsyncTask; -import android.util.Log; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; - - -/** - * Извлечение Json по URL - */ -public class Extractor extends AsyncTask { - private final String URLSingers = "http://cache-default06g.cdn.yandex.net/download.cdn.yandex.net/mobilization-2016/artists.json"; - private HttpURLConnection urlConnection = null; - private String resultJson = ""; - - public AsyncResponse delegate = null; - - public interface AsyncResponse { - /** - * Вызывается по окончании извлечения данных из json - */ - void processFinish(String output); - } - - public Extractor(AsyncResponse delegate) { - this.delegate = delegate; - } - - @Override - protected String doInBackground(Void... params) { - // получаем данные с внешнего ресурса - try { - URL url = new URL(URLSingers); - urlConnection = (HttpURLConnection) url.openConnection(); - urlConnection.setRequestMethod("GET"); - urlConnection.connect(); - - InputStream inputStream = urlConnection.getInputStream(); - StringBuilder buffer = new StringBuilder(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - String line; - while ((line = reader.readLine()) != null) { - buffer.append(line); - } - - resultJson = buffer.toString(); - } catch (MalformedURLException e) { - Log.e("ERROR", "URL is not available"); - } catch (IOException ex) { - Log.e("ERROR", "Cannot open url connection."); - } finally { - if (urlConnection != null) { - urlConnection.disconnect(); - } - } - return resultJson; - } - - @Override - protected void onPostExecute(String strJson) { - super.onPostExecute(strJson); - delegate.processFinish(strJson); - } - -} \ No newline at end of file diff --git a/Singers/app/src/main/java/ru/daria/singers/HomeActivity.java b/Singers/app/src/main/java/ru/daria/singers/HomeActivity.java index a5984d2..eea1d37 100644 --- a/Singers/app/src/main/java/ru/daria/singers/HomeActivity.java +++ b/Singers/app/src/main/java/ru/daria/singers/HomeActivity.java @@ -1,7 +1,9 @@ package ru.daria.singers; import android.app.Activity; +import android.app.LoaderManager; import android.content.Intent; +import android.content.Loader; import android.os.Bundle; import android.util.Log; import android.view.View; @@ -21,33 +23,48 @@ /** * Activity для отображения окна приветствия, загрузки списка исполнителей */ -public class HomeActivity extends Activity { +public class HomeActivity extends Activity implements LoaderManager.LoaderCallbacks { List singers = new ArrayList(); + final int LOADER_ID = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.splash); - Extractor ex = new Extractor(new Extractor.AsyncResponse() { - @Override - public void processFinish(String output) { - try { - JSONArray dataJson = new JSONArray(output); - singers = getSingersFromJson(dataJson); - Intent i = new Intent(HomeActivity.this, MainActivity.class); - i.putExtra("SINGERS", (Serializable) singers); - startActivity(i); - finish(); - } catch (JSONException ex) { - ex.printStackTrace(); - Button b = (Button) findViewById(R.id.tryAgainButton); - b.setVisibility(View.VISIBLE); - TextView v = (TextView) findViewById(R.id.splashText); - v.setText("Невозможно загрузить список исполнителей."); - } - } - }); - ex.execute(); + Loader loader = getLoaderManager().initLoader(LOADER_ID, null, this); + loader.forceLoad(); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + Loader loader = null; + if (id == LOADER_ID) { + loader = new DataLoader(this); + } + return loader; + } + + @Override + public void onLoadFinished(Loader loader, String data) { + try { + JSONArray dataJson = new JSONArray(data); + singers = getSingersFromJson(dataJson); + Intent i = new Intent(HomeActivity.this, MainActivity.class); + i.putExtra("SINGERS", (Serializable) singers); + startActivity(i); + finish(); + } catch (JSONException ex) { + ex.printStackTrace(); + Button b = (Button) findViewById(R.id.tryAgainButton); + b.setVisibility(View.VISIBLE); + TextView v = (TextView) findViewById(R.id.splashText); + v.setText("Невозможно загрузить список исполнителей."); + } + + } + + @Override + public void onLoaderReset(Loader loader) { } public void buttonOnClick(View view) { @@ -109,5 +126,4 @@ public List getSingersFromJson(JSONArray jSingers) { } return singers; } - } diff --git a/Singers/app/src/main/java/ru/daria/singers/HomeFragment.java b/Singers/app/src/main/java/ru/daria/singers/HomeFragment.java deleted file mode 100644 index 8c64fbe..0000000 --- a/Singers/app/src/main/java/ru/daria/singers/HomeFragment.java +++ /dev/null @@ -1,131 +0,0 @@ -package ru.daria.singers; - -import android.app.Fragment; -import android.app.FragmentManager; -import android.app.FragmentTransaction; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Created by dsukmanova on 16.07.16. - */ -public class HomeFragment extends Fragment { - List singers = new ArrayList(); - View view; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public View onCreateView(LayoutInflater inflater, - ViewGroup container, - Bundle savedInstanceState) { - - view = inflater.inflate(R.layout.splash, container, false); - Extractor ex = new Extractor(new Extractor.AsyncResponse() { - @Override - public void processFinish(String output) { - try { - JSONArray dataJson = new JSONArray(output); - singers = getSingersFromJson(dataJson); - Bundle arg = new Bundle(); - arg.putSerializable("SINGERS", (Serializable) singers); - MainFragment fragment = new MainFragment(); - fragment.setArguments(arg); - - FragmentManager fragmentManager = getFragmentManager(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.replace(R.id.fragmentContainer, fragment); - fragmentTransaction.addToBackStack(null); - fragmentTransaction.commit(); - } catch (JSONException ex) { - ex.printStackTrace(); - Button b = (Button) view.findViewById(R.id.tryAgainButton); - b.setVisibility(View.VISIBLE); - TextView v = (TextView) view.findViewById(R.id.splashText); - v.setText("Невозможно загрузить список исполнителей."); - } - } - }); - ex.execute(); - return view; - } - - public void buttonOnClick(View view) { - Button b = (Button) view.findViewById(R.id.tryAgainButton); - b.setVisibility(View.INVISIBLE); - - } - - /** - * Функция создает список исполнителей по входному json - * - * @param jSingers JSONArray Массив исполнителей в формате json - */ - public List getSingersFromJson(JSONArray jSingers) { - List singers = new ArrayList<>(); - for (int i = 0; i < jSingers.length(); i++) { - try { - JSONObject jSinger = jSingers.getJSONObject(i); - Long id = null; - if (jSinger.has("id")) id = jSinger.getLong("id"); - String name = ""; - if (jSinger.has("name")) name = jSinger.getString("name"); - List genres = new ArrayList<>(); - if (jSinger.has("genres")) { - JSONArray jGenres = jSinger.getJSONArray("genres"); - for (int j = 0; j < jGenres.length(); j++) { - genres.add(jGenres.getString(j)); - } - } - int tracks = 0; - if (jSinger.has("tracks")) tracks = jSinger.getInt("tracks"); - int albums = 0; - if (jSinger.has("albums")) albums = jSinger.getInt("albums"); - String link = ""; - if (jSinger.has("link")) link = jSinger.getString("link"); - String description = ""; - if (jSinger.has("description")) { - description = jSinger.getString("description"); - //описание будет всегда с заглавной буквы - if (description.length() > 0) { - description = description.substring(0, 1).toUpperCase() + description.substring(1); - } - } - - Map covers = new LinkedHashMap<>(); - if (jSinger.has("cover")) { - JSONObject jCovers = jSinger.getJSONObject("cover"); - String small = jCovers.getString("small"); - String big = jCovers.getString("big"); - if (small != null) covers.put(Singer.coverTypes.small, small); - if (big != null) covers.put(Singer.coverTypes.big, big); - } - Singer singer = new Singer(id, name, genres, tracks, albums, link, description, covers); - singers.add(singer); - } catch (JSONException ex) { - Log.e("ERROR", String.format("getJSONObject(%d) occurred an error", i)); - } - } - return singers; - } - -} From 691becf572ff4e4f44e11b3d26681d40ea05ec3c Mon Sep 17 00:00:00 2001 From: dsukmanova Date: Sun, 17 Jul 2016 22:30:48 +0300 Subject: [PATCH 04/24] Add menu with info about app --- .../ru/daria/singers/AboutProgramDialog.java | 26 ++++++++++++ .../java/ru/daria/singers/MainActivity.java | 18 +++++++- .../app/src/main/res/layout/about_program.xml | 41 +++++++++++++++++++ .../app/src/main/res/menu/options_menu.xml | 5 ++- Singers/app/src/main/res/values/strings.xml | 8 ++++ 5 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 Singers/app/src/main/java/ru/daria/singers/AboutProgramDialog.java create mode 100644 Singers/app/src/main/res/layout/about_program.xml diff --git a/Singers/app/src/main/java/ru/daria/singers/AboutProgramDialog.java b/Singers/app/src/main/java/ru/daria/singers/AboutProgramDialog.java new file mode 100644 index 0000000..1bd399c --- /dev/null +++ b/Singers/app/src/main/java/ru/daria/singers/AboutProgramDialog.java @@ -0,0 +1,26 @@ +package ru.daria.singers; + +import android.app.DialogFragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * Created by dsukmanova on 17.07.16. + */ +public class AboutProgramDialog extends DialogFragment { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance){ + View view = inflater.inflate(R.layout.about_program, null); + view.findViewById(R.id.okButton).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getDialog().dismiss(); + } + }); + getDialog().setTitle(R.string.aboutTitle); + return view; + } + +} diff --git a/Singers/app/src/main/java/ru/daria/singers/MainActivity.java b/Singers/app/src/main/java/ru/daria/singers/MainActivity.java index 47c9554..b383975 100644 --- a/Singers/app/src/main/java/ru/daria/singers/MainActivity.java +++ b/Singers/app/src/main/java/ru/daria/singers/MainActivity.java @@ -1,5 +1,7 @@ package ru.daria.singers; +import android.app.DialogFragment; +import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.SearchManager; @@ -67,17 +69,29 @@ public boolean onQueryTextChange(String newText) { } }; searchView.setOnQueryTextListener(textChangeListener); + return super.onCreateOptionsMenu(menu); } - public void showMenuVisible (Menu menu, boolean showMenu){ - if(menu == null) return; + public void showMenuVisible(Menu menu, boolean showMenu) { + if (menu == null) return; menu.setGroupVisible(R.id.main_menu_group, showMenu); } @Override public boolean onOptionsItemSelected(MenuItem item) { + //пункт меню "О программе" + switch (item.getItemId()) { + case R.id.about: + FragmentManager fragmentManager = getFragmentManager(); + AboutProgramDialog aboutProgramDialog = new AboutProgramDialog(); + aboutProgramDialog.show(fragmentManager, "О программе"); + break; + default: + break; + } return super.onOptionsItemSelected(item); + } @Override diff --git a/Singers/app/src/main/res/layout/about_program.xml b/Singers/app/src/main/res/layout/about_program.xml new file mode 100644 index 0000000..8d9cdcc --- /dev/null +++ b/Singers/app/src/main/res/layout/about_program.xml @@ -0,0 +1,41 @@ + + + + + + + + + +