+ Listview Adapter class

+ iTunes API response parser
+ Artists listview loader
+ Search functionality
+ Search timer logic
This commit is contained in:
HAKO-PC\Hako
2017-12-30 13:40:43 -03:00
parent 231fe6e412
commit 47547816fc
7 changed files with 131 additions and 24 deletions

View File

@@ -3,20 +3,31 @@ package com.hakodev.androiditunesapi.activities;
import android.Manifest; import android.Manifest;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout; import android.support.constraint.ConstraintLayout;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log; import android.util.Log;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
import com.anthonycr.grant.PermissionsManager; import com.anthonycr.grant.PermissionsManager;
import com.anthonycr.grant.PermissionsResultAction; import com.anthonycr.grant.PermissionsResultAction;
import com.google.gson.Gson;
import com.hakodev.androiditunesapi.AndroidItunesAPI; import com.hakodev.androiditunesapi.AndroidItunesAPI;
import com.hakodev.androiditunesapi.R; import com.hakodev.androiditunesapi.R;
import com.hakodev.androiditunesapi.adapters.ArtistsListAdapter;
import com.hakodev.androiditunesapi.models.ItunesResponse;
import com.hakodev.androiditunesapi.models.Result;
import com.hakodev.androiditunesapi.util.Utils; import com.hakodev.androiditunesapi.util.Utils;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Callback; import okhttp3.Callback;
@@ -28,9 +39,17 @@ public class ArtistListActivity extends AppCompatActivity {
private final static String TAG = "ArtistListActivity"; private final static String TAG = "ArtistListActivity";
private final static String SEARCH_URL = "https://itunes.apple.com/search?term=%1$s&country=US&entity=musicArtist&limit=10"; private final static String SEARCH_URL = "https://itunes.apple.com/search?term=%1$s&country=US&entity=musicArtist&limit=10";
private final static String[] DEMO_ARTISTS = {"Valentine", "Children", "Red"};
private OkHttpClient networkClient; private OkHttpClient networkClient;
private ArtistsListAdapter artistsListAdapter;
private ArrayList<String> artistsList = new ArrayList<>();
private ConstraintLayout lytBase; private ConstraintLayout lytBase;
private ListView listArtists;
private EditText txtArtistSearch;
private Timer keypressTimer = new Timer();
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -40,6 +59,9 @@ public class ArtistListActivity extends AppCompatActivity {
setupViews(); setupViews();
init(); init();
askForPermissions(); askForPermissions();
int randomArtistIndex = new Random().nextInt(DEMO_ARTISTS.length);
requestArtist(DEMO_ARTISTS[randomArtistIndex]);
} }
@Override @Override
@@ -53,10 +75,40 @@ public class ArtistListActivity extends AppCompatActivity {
private void setupViews() { private void setupViews() {
lytBase = findViewById(R.id.lytBase); lytBase = findViewById(R.id.lytBase);
listArtists = findViewById(R.id.listArtists);
txtArtistSearch = findViewById(R.id.txtArtistSearch);
txtArtistSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable txt) {
keypressTimer.cancel();
keypressTimer = new Timer();
keypressTimer.schedule(
new TimerTask() {
@Override
public void run() {
if (txt.toString().length() > 3){
requestArtist(txt.toString());
}
}
}, 200);
}
});
} }
private void init() { private void init() {
networkClient = AndroidItunesAPI.getInstance().getNetworkClient(); networkClient = AndroidItunesAPI.getInstance().getNetworkClient();
artistsListAdapter = new ArtistsListAdapter(this, artistsList);
listArtists.setAdapter(artistsListAdapter);
} }
private void askForPermissions() { private void askForPermissions() {
@@ -90,10 +142,26 @@ public class ArtistListActivity extends AppCompatActivity {
@Override @Override
public void onResponse(@NonNull Call call, @NonNull final Response response) throws IOException { public void onResponse(@NonNull Call call, @NonNull final Response response) throws IOException {
String res = response.body().string(); String body = response.body().string();
Log.w(TAG, res); Log.w(TAG, body);
buildArtistsList(parseArtistsResponse(body));
} }
}); });
}).start(); }).start();
} }
private ArrayList<String> parseArtistsResponse(String body) {
ItunesResponse itunesResponse = new Gson().fromJson(body, ItunesResponse.class);
ArrayList<String> artistsNames = new ArrayList<>();
for (Result artist : itunesResponse.getResults()) {
artistsNames.add(artist.getArtistName());
}
return artistsNames;
}
private void buildArtistsList(ArrayList<String> artists) {
artistsList.clear();
artistsList.addAll(artists);
runOnUiThread(() -> artistsListAdapter.notifyDataSetChanged());
}
} }

View File

@@ -0,0 +1,41 @@
package com.hakodev.androiditunesapi.adapters;
import android.content.Context;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.hakodev.androiditunesapi.R;
import java.util.ArrayList;
public class ArtistsListAdapter extends ArrayAdapter<String> {
private final Context context;
private final ArrayList<String> values;
public ArtistsListAdapter(Context context, ArrayList<String> values) {
super(context, R.layout.artists_list_adapter, values);
this.context = context;
this.values = values;
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
if (inflater != null) {
convertView = inflater.inflate(R.layout.artists_list_adapter, parent, false);
}
}
TextView textView = convertView.findViewById(R.id.lblArtistName);
ImageView imageView = convertView.findViewById(R.id.imgArtist);
textView.setText(values.get(position));
imageView.setImageResource(R.drawable.default_artist);
return convertView;
}
}

View File

@@ -5,20 +5,20 @@ import com.google.gson.annotations.SerializedName;
import java.util.List; import java.util.List;
public class Response { public class ItunesResponse {
@SerializedName("resultCount") @SerializedName("resultCount")
@Expose @Expose
private Long resultCount; private int resultCount;
@SerializedName("results") @SerializedName("results")
@Expose @Expose
private List<Result> results = null; private List<Result> results = null;
public Long getResultCount() { public int getResultCount() {
return resultCount; return resultCount;
} }
public void setResultCount(Long resultCount) { public void setResultCount(int resultCount) {
this.resultCount = resultCount; this.resultCount = resultCount;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -5,7 +5,9 @@
android:id="@+id/lytBase" android:id="@+id/lytBase"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="com.hakodev.androiditunesapi.activities.ArtistListActivity"> tools:context="com.hakodev.androiditunesapi.activities.ArtistListActivity"
android:focusable="true"
android:focusableInTouchMode="true">
<EditText <EditText
android:id="@+id/txtArtistSearch" android:id="@+id/txtArtistSearch"
@@ -24,13 +26,11 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ListView <ListView
android:id="@+id/listView" android:id="@+id/listArtists"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginBottom="8dp" android:layout_margin="16dp"
android:layout_marginEnd="8dp" android:background="@color/colorAccent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@@ -2,17 +2,14 @@
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="58dp"
android:layout_gravity="center_vertical"> android:layout_gravity="center_vertical">
<ImageView <ImageView
android:id="@+id/imgArtist" android:id="@+id/imgArtist"
android:layout_width="36dp" android:layout_width="36dp"
android:layout_height="36dp" android:layout_height="36dp"
android:layout_marginBottom="8dp" android:layout_margin="16dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:contentDescription="@string/description_artists_image" android:contentDescription="@string/description_artists_image"
android:src="@drawable/default_artist" android:src="@drawable/default_artist"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -21,14 +18,12 @@
<TextView <TextView
android:id="@+id/lblArtistName" android:id="@+id/lblArtistName"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_margin="16dp"
android:layout_marginEnd="8dp" android:textSize="18sp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@+id/imgArtist"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>

View File

@@ -10,6 +10,9 @@
<item name="android:textColor">@color/colorText</item> <item name="android:textColor">@color/colorText</item>
<item name="android:textColorSecondary">@color/colorTextSecondary</item> <item name="android:textColorSecondary">@color/colorTextSecondary</item>
<item name="android:textColorHint">@color/colorHintText</item> <item name="android:textColorHint">@color/colorHintText</item>
<item name="colorControlNormal">@color/colorPrimary</item>
<item name="android:editTextColor">@color/colorText</item>
</style> </style>
<style name="AppTheme.NoActionBar"> <style name="AppTheme.NoActionBar">