I am new to Android app development. I am trying to display the image and text in another Activity from the item of the Recyclerview which was clicked by the user. I am getting unreachable statement error. Please help me out!
Here's my code for getting image:
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child));
and the full Activity code:
public class RestaurantsAndCafesActivity extends Activity {
public static final String URL = "http://192.168.8.101:80/jay.html";
private RecyclerView mRecyclerView;
private RCRecyclerAdapter adapter;
public String imgUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reyclerview_layout);
/* Initialize RecyclerView */
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//parseResult();
new getDataAsyncTask().execute();
final GestureDetector mGestureDetector = new GestureDetector(RestaurantsAndCafesActivity.this, new GestureDetector.SimpleOnGestureListener() {
#Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
View child = recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());
if(child!=null && mGestureDetector.onTouchEvent(motionEvent)){
Toast.makeText(RestaurantsAndCafesActivity.this,"Clicked Number "+recyclerView.getChildPosition(child), Toast.LENGTH_SHORT).show();
return true;
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
});
}
public class getDataAsyncTask extends AsyncTask<Void,Void,Void>{
ArrayList<FeedItem> arrayList = new ArrayList<>();
public String getImageUrl(int pos)
{
return arrayList.get(pos).thumb;
}
#Override
protected Void doInBackground(Void... params) {
try {
org.jsoup.nodes.Document document = Jsoup.connect(URL).get();
for(Element e : document.select("img[src]"))
{
Elements imgScr = e.select("img[src]");
String elements = imgScr.attr("src");
String text = imgScr.attr("alt");
String desc = imgScr.attr("title");
arrayList.add(new FeedItem(text, elements, desc));
}
}
catch(IOException e)
{
e.printStackTrace();
}
return null;
}
ProgressDialog progressDialog;
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(RestaurantsAndCafesActivity.this,"Loading","Please Wait",true,false);
}
#Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
adapter = new RCRecyclerAdapter(getApplicationContext(),arrayList);
mRecyclerView.setAdapter(adapter);
}
}
}
I just want to get the image url so that I can send it to another Activity via Intent.putExtra method. Please tell me where I am going wrong, or is there any other way for what I am trying to achieve?
In your onInterceptTouchEvent the
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child)); needs to be before return true. It's declared after return true; which makes the statement unreachable.
Related
I have a recyclerView with a list of Competitor objects. The list that populates the RecyclerView is a global Singleton. In that Singleton's constructor I open a Json file, parse it's contents to populate the global Singleton's list of Competitors and use that list to pass to the RecyclerView's adapter. Each list item has an ImageButton. This is what I'm trying to accomplish;
When the user clicks on the ImageButton (Delete Button) I want an AlertDialog to pop up and ask the user if they are sure they want to delete the Competitor. This part I have so far. But what I need to do next I can't figure out. I am able to update the json file that contains the global list's information but I also want to update the recyclerview by removing the Competitor from the RecyclerView by calling:
mCompetitorsList.remove(competitor); notifyItemRemoved(position);
However I can't get a reference to the mCompetitorsList variable from an external Dialog class. The same goes for calling notifiyItemRemoved(position)
What should I do? Below is the code for my Dialog class, my Activity that contains the RecyclerView and it's Adapter as well as the Singleton implementation.
public class MasterCompetitorsListActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
private static final String DIALOG_DELETE_COMPETITOR = "DIALOG_DELETE_COMPETITOR";
private RecyclerView mRecyclerView;
private List<Competitor> mCompetitorsList;
private CompetitorListAdapter mAdapter;
private SearchView mSearchView;
private FloatingActionButton mAddCompetitorButton;
private Button mDeletCompetitor;
private TextView mCompetitorHidden;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_master_competitors_list);
mSearchView = (SearchView) findViewById(R.id.searchView);
mSearchView.setOnQueryTextListener(this);
/* initialize the Global Competitor's List for the recyclerview. Because this is a singleton
it should initialize the list for the entire app's runtime
*/
GlobalCompetitorsList.get();
mCompetitorsList = GlobalCompetitorsList.getCompetitors();
mRecyclerView = (RecyclerView) findViewById(R.id.master_competitors_recycler);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
mAdapter = new CompetitorListAdapter(this, mCompetitorsList);
mRecyclerView.setAdapter(mAdapter);
// set a separator for the list items
DividerItemDecoration divider = new DividerItemDecoration(
mRecyclerView.getContext(),
layoutManager.getOrientation());
divider.setDrawable(ContextCompat.getDrawable(MasterCompetitorsListActivity.this, R.drawable.divider_dark));
mRecyclerView.addItemDecoration(divider);
mRecyclerView.setAdapter(mAdapter);
mAddCompetitorButton = (FloatingActionButton) findViewById(R.id.add_master_competitor_floating_button);
mAddCompetitorButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MasterCompetitorsListActivity.this, AddNewMasterCompetitorActivity.class);
startActivity(intent);
}
});
}
#Override
public boolean onQueryTextSubmit(String query) {
mCompetitorsList = new ArrayList<>();
mCompetitorsList = GlobalCompetitorsList.getCompetitors();
mAdapter.notifyDataSetChanged();
return false;
}
#Override
public boolean onQueryTextChange(String query) {
mCompetitorsList = GlobalCompetitorsList.getCompetitors();
query = query.toLowerCase();
final List<Competitor> filteredList = new ArrayList<>();
for (int i = 0; i < mCompetitorsList.size(); i++) {
final String lastName = mCompetitorsList.get(i).getLastName().toLowerCase();
final String firstName = mCompetitorsList.get(i).getFirstName().toLowerCase();
if (lastName.contains(query) || firstName.contains(query)) {
filteredList.add(mCompetitorsList.get(i));
}
}
mAdapter.setFilter(filteredList);
return true;
}
// ********* RecyclerView Adapter class *************************************************************************
public class CompetitorListAdapter extends RecyclerView.Adapter<CompetitorListAdapter.CompetitorViewHolder> {
List<Competitor> mCompetitors;
Context mContext;
public CompetitorListAdapter(Context context, List<Competitor> competitors) {
mContext = context;
mCompetitors = competitors;
}
#Override
public CompetitorListAdapter.CompetitorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(MasterCompetitorsListActivity.this);
View itemView = inflater.inflate(R.layout.list_item_master_competitor, parent, false);
CompetitorViewHolder viewHolder = new CompetitorViewHolder(itemView);
return viewHolder;
}
#Override
public void onBindViewHolder(CompetitorListAdapter.CompetitorViewHolder holder, final int position) {
final Competitor competitor = mCompetitorsList.get(position);
try {
holder.firstName.setText(competitor.getFirstName());
holder.lastName.setText(competitor.getLastName());
holder.memberNum.setText(competitor.getMemberNum());
holder.deleteCompetitor.setImageResource(R.drawable.ic_delete_forever_white_24dp);
holder.container.findViewById(R.id.main_container);
holder.hiddenCompetitorId.setText(competitor.getCompetitorId().toString());
} catch (Exception e) {
e.printStackTrace();
}
holder.deleteCompetitor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager = getSupportFragmentManager();
DeleteCompetitorDialogFragment dialog = new DeleteCompetitorDialogFragment();
dialog.show(fragmentManager, DIALOG_DELETE_COMPETITOR);
// mCompetitorsList.remove(competitor); // remove from the global singleton list
// notifyItemRemoved(position);
}
});
}
#Override
public int getItemCount() {
return mCompetitorsList.size();
}
// ************* View Holder Class **************************************************************************
public class CompetitorViewHolder extends RecyclerView.ViewHolder {
public TextView firstName;
public TextView lastName;
public TextView memberNum;
public ImageButton deleteCompetitor;
public ConstraintLayout container;
public TextView hiddenCompetitorId;
boolean comptitorIsActive = false;
public CompetitorViewHolder(final View itemView) {
super(itemView);
firstName = (TextView) itemView.findViewById(R.id.first_name);
lastName = (TextView) itemView.findViewById(R.id.last_name);
deleteCompetitor = (ImageButton) itemView.findViewById(R.id.delete_competitor_button);
hiddenCompetitorId = (TextView) itemView.findViewById(R.id.competitor_id_hidden);
container = (ConstraintLayout) itemView.findViewById(R.id.main_container);
memberNum = (TextView) itemView.findViewById(R.id.member_num);
}
}
// ************ End of View Holder Class ********************************************************************
public void setFilter(List<Competitor> newList) {
mCompetitorsList = new ArrayList<>();
mCompetitorsList.addAll(newList);
notifyDataSetChanged();
}
}
// ************* End of RecyclerView Adapter class **********************************************************
}
Here is the Dialog class:
public class DeleteCompetitorDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
final GlobalCompetitorsList mCompetitorsList = GlobalCompetitorsList.get();
return new AlertDialog.Builder(getActivity())
.setTitle("Delete this Competitor?")
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// remove from the master_competitors.json file by overwriting the original file with the new
// global list
File file = new File("data/data/com.checkinsystems.ez_score/files/master_competitors.json");
if (file.exists()) {
FileOutputStream fos = null;
try {
String jsonString = new Gson().toJson(mCompetitorsList);
fos = getActivity().openFileOutput("master_competitors.json", getActivity().MODE_PRIVATE);
fos.write(jsonString.getBytes());
// somehow access the list from the calling activity to remove the item
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert fos != null;
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
})
.create();
}
}
And if it helps to understand my code, here is the Singleton class
public class GlobalCompetitorsList {
public static GlobalCompetitorsList sGlobalCompetitorsList;
public static List<Competitor> sCompetitors;
public static GlobalCompetitorsList get() {
if(sGlobalCompetitorsList == null){
return new GlobalCompetitorsList();
} else {
return sGlobalCompetitorsList;
}
}
private GlobalCompetitorsList() {
File file = new File("data/data/com.checkinsystems.ez_score/files/master_competitors.json");
String jsonString;
if(file.exists()){
BufferedReader reader = null;
List<Competitor> list;
sCompetitors = new ArrayList<>();
try {
reader = new BufferedReader(new FileReader(file));
jsonString = reader.readLine();
Type compType = new TypeToken<List<Competitor>>(){}.getType();
list = new Gson().fromJson(jsonString, compType);
addCompetitors(list);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert reader != null;
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
sCompetitors = new ArrayList<>();
}
}
public void addCompetitor(Competitor c){
sCompetitors.add(c);
}
public static void addCompetitors(List<Competitor> c){
sCompetitors.addAll(c);
}
public static List<Competitor> getCompetitors(){
return sCompetitors;
}
}
Simple just create a constructor for the Dialog that you are using
public DeleteCompetitorDialogFragment(IMyListenerCallback listener){
mListener = listener;
}
later on//
if(listener != null){
listener.doWhatYouNeed(stuffToPass);
}
Then make an interface class
public interface IMyListenerCallback{
void doWhatYouNeed(Object stuffToPass);
}
//then in your calling activity
public class MainActivity extends AppCompatActivity implements IMyListenerCallback{
private void launchDialog(){
new DeleteCompetitorDialogFragment(this).show();
}
#Override
public void doWhatYouNeed(Object stuffToPass){
}
}
Of course this is pseduo code and not tested, but hopefully you get the picture. Goodluck.
I've tried to find out how to get selected id of the ratingBar in ListView on net, but almost of them using ListViewAdapter or RatingAdapter on another class. I don't know how to do, because I do not yet know about it, so all my classes declared in MainActivity including ListView.
I have a TextView and RatingBar on each list in ListView,
but the issue is how to send each list of RatingBar that already fills into server without create a new class of ListViewAdapter or RatingAdapter??
here is my full code how it's work to display the TextView and RatingBar on each list:
public class Pertanyaan extends AppCompatActivity {
private String TAG = Pertanyaan.class.getSimpleName();
private ProgressDialog pDialog;
private ListView lv;
private Button kirim;
private RatingBar rate;
ArrayList<HashMap<String, String>> contactList;
#Override
public void onBackPressed() {
super.onBackPressed();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pertanyaan);
contactList = new ArrayList<>();
TextView textdosen=(TextView)findViewById(R.id.dosen);
TextView textmatkul=(TextView)findViewById(R.id.matkul);
final TextView txtrate=(TextView)findViewById(R.id.txtrating);
kirim = (Button)findViewById(R.id.btn);
rate=(RatingBar)findViewById(R.id.rating);
Bundle b=getIntent().getExtras();
String dosen=b.getString("dosen");
String matkul=b.getString("matkul");
textdosen.setText(dosen);
textmatkul.setText(matkul);
lv = (ListView) findViewById(R.id.list);
new GetContacts().execute();
}
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(Pertanyaan.this);
pDialog.setMessage("Menampilkan Pertanyaan...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String url = "http://flix.16mb.com/send_data.php";
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONArray jsonObj = new JSONArray(jsonStr);
// looping through All Contacts
for (int i = 0; i < jsonObj.length(); i++) {
JSONObject c = jsonObj.getJSONObject(i);
String id = c.getString("id");
String ask = c.getString("ask");
HashMap<String, String> pertanyaans = new HashMap<>();
pertanyaans.put("id", id);
pertanyaans.put("ask", ask);
contactList.add(pertanyaans);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
Pertanyaan.this, contactList,
R.layout.list_pertanyaan, new String[]{"ask", "id"}, new int[]{R.id.ask, R.id.txtid});
lv.setAdapter(adapter);
}
}
}
can someone give me a hint what should i do?
Ok here is a sample application so that it should give you some help:
First of all you need to create a CustomAdapter because SimpleAdapter has limitations. Secondly you need to use RecyclerView instead of ListView. After that you need to register a click event when the user clicks on the list that you have made. For those things we come with the following:
The Model of the list:
public class CustomList {
private String id, ask;
public CustomList(String id, String ask) {
this.id = id;
this.ask = ask;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAsk() {
return ask;
}
public void setAsk(String ask) {
this.ask = ask;
}
}
then the layout for each list item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:padding="15dp"
android:layout_height="wrap_content">
<TextView
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/id_text"
android:layout_weight="4" />
<TextView
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/ask_text"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
then the layout for RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="kostas.testexample.com.testexample.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/myRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
then the custom adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder>{
private List<CustomList> items;
private Context context;
public CustomAdapter(List<CustomList> items, Context context){
this.items = items;
this.context = context;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item, parent, false);
return new CustomViewHolder(v);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
holder.itemId.setText(items.get(position).getId());
holder.itemAsk.setText(items.get(position).getAsk());
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
class CustomViewHolder extends RecyclerView.ViewHolder {
TextView itemId;
TextView itemAsk;
CustomViewHolder(View itemView) {
super(itemView);
itemId = (TextView)itemView.findViewById(R.id.id_text);
itemAsk = (TextView)itemView.findViewById(R.id.ask_text);
}
}
}
then you add them all up in MainActivity like this:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private LinearLayoutManager layoutManager;
private URL url;
private HttpURLConnection httpURLConnection;
private CustomAdapter customAdapter;
private ProgressDialog pDialog;
private String id, ask;
private List<CustomList> customList = new ArrayList<>();
private StringBuilder jsonResult;
private JSONObject jsonChildNode;
private JSONArray jsonResponse;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.myRecyclerView);
layoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);
accessWebService();
clickEvent();
}
private void clickEvent() {
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(MainActivity.this, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "Item Clicked at position: " + position + " with id: " + customList.get(position).getId() + " and ask is: " + customList.get(position).getAsk(), Toast.LENGTH_SHORT).show();
}
}));
}
public class JsonReadTask extends AsyncTask<String , Void, List<CustomList>> {
public JsonReadTask() {
super();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setIndeterminate(true);
pDialog.setMessage("Please Wait");
pDialog.setCancelable(false);
pDialog.setInverseBackgroundForced(true);
// pDialog.show();
}
#Override
protected List<CustomList> doInBackground(String... params) {
try {
url = new URL(params[0]);
httpURLConnection =(HttpURLConnection) url.openConnection();
httpURLConnection.connect();
InputStream in = new BufferedInputStream(httpURLConnection.getInputStream());
jsonResult = inputStreamToString(in, MainActivity.this);
jsonResponse = new JSONArray(jsonResult.toString());
for (int i = 0; i < jsonResponse.length(); i++) {
jsonChildNode = jsonResponse.getJSONObject(i);
id = jsonChildNode.optString("id");
ask = jsonChildNode.optString("ask");
customList.add(new CustomList(id, ask));
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return customList;
}
#Override
protected void onPostExecute(List<CustomList> customList) {
if(customList == null){
Log.d("ERORR", "No result to show.");
return;
}
ListDrawer(customList);
pDialog.dismiss();
}
}
public static StringBuilder inputStreamToString(InputStream is, Activity activity) {
String rLine;
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
} catch (Exception e) {
activity.finish();
}
return answer;
}
private void ListDrawer(List<CustomList> customList) {
customAdapter = new CustomAdapter(customList, MainActivity.this);
customAdapter.notifyDataSetChanged();
recyclerView.setAdapter(customAdapter);
}
public void accessWebService() {
JsonReadTask task = new JsonReadTask();
task.execute("http://flix.16mb.com/send_data.php");
}
}
and then you need the customListener for RecyclerView
public class RecyclerItemClickListener implements OnItemTouchListener {
private OnItemClickListener mListener;
private OnLongItemClickListener mLongListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
interface OnLongItemClickListener{
boolean onLongItemClicked(int position);
}
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
public RecyclerItemClickListener(Context context, OnLongItemClickListener listener) {
mLongListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.OnGestureListener() {
#Override
public boolean onDown(MotionEvent e) {
return false;
}
#Override
public void onShowPress(MotionEvent e) {
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
#Override
public void onLongPress(MotionEvent e) {
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
which produces the following result:
but do not forget to add to build.gradle(Module: app) the following:
compile 'com.android.support:recyclerview-v7:25.0.1'
and in your Manifest.xml the permission:
<uses-permission android:name="android.permission.INTERNET"/>
Hope it helps and give you a hint on how to do stuff!!!
I am working on a shopping cart app,Items are displayed as below.There is a plus, minus (+/-) buttons to choose the number of quantity.
If product quantity is changed, I need to pass "productname" and "quantity" to the main activity so that I could use them to prepare final cart. I got some suggestions to use database or some content providers,
I am not sure how to do it.., please help
MainActivity.java
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
RecycleAdapter recycleAdapter;
List<HashMap<String, String>> onlineData;
ProgressDialog pd;
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyle_view);
toolbar= (Toolbar) findViewById(R.id.anim_toolbar);
setSupportActionBar(toolbar);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getBaseContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
final String url = "http://www.qa4.org/?json=get_recent_posts&count=45";
new AsyncHttpTask().execute(url);
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
pd=new ProgressDialog(MainActivity.this);
pd.requestWindowFeature(Window.FEATURE_NO_TITLE);
pd.setMessage("Loading please wait...");
pd.setCancelable(false);
pd.show();
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
e.printStackTrace();
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
// Download complete. Let us update UI
pd.dismiss();
if (result == 1) {
recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData);
recyclerView.setAdapter(recycleAdapter);
} else {
Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
}
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
onlineData = new ArrayList<>();
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
HashMap<String, String> item = new HashMap<>();
item.put("title", post.optString("title"));
JSONArray jsonArray = post.getJSONArray("attachments");
JSONObject jsonObject1 = jsonArray.getJSONObject(0);
JSONObject jsonArrayImages = jsonObject1.getJSONObject("images");
JSONObject jsonArrayThumb = jsonArrayImages.getJSONObject("thumbnail");
item.put("thump", jsonArrayThumb.optString("url"));
onlineData.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
RecycleAdapter.java
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolderRec> {
List<HashMap<String, String>> onlineData;
SQLiteDatabase db;
Context context;
RecycleAdapter(Context context,List<HashMap<String, String>> onlineData){
this.onlineData = onlineData;
this.context=context;
}
#Override
public ViewHolderRec onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolderRec( LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycle, parent, false));
}
#Override
public void onBindViewHolder(ViewHolderRec holder, int position) {
HashMap<String,String> map =onlineData.get(position);
//Download image using picasso library
Picasso.with(context).load(map.get("thump"))
.error(R.drawable.placeholder)
.placeholder(R.drawable.placeholder)
.into(holder.iv);
holder.tv.setText(map.get("title"));
}
#Override
public int getItemCount() {
return onlineData.size();
}
public class ViewHolderRec extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView iv;
TextView tv, quantity;
ImageView Add_Cart;
ImageView Remove_Cart;
public ViewHolderRec(View itemView) {
super(itemView);
iv = (ImageView) itemView.findViewById(R.id.thumbnail);
tv = (TextView) itemView.findViewById(R.id.title);
quantity = (TextView)itemView.findViewById(R.id.cart_qty);
Add_Cart = (ImageView)itemView.findViewById(R.id.cart_add);
Remove_Cart = (ImageView)itemView.findViewById(R.id.cart_remove);
itemView.setOnClickListener(this);
Add_Cart.setOnClickListener(this);
Remove_Cart.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == Add_Cart.getId()){
increment();
}
else if(v.getId() == Remove_Cart.getId()){
decrement();
}
}
public void increment(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(++currentNos));
}
public void decrement(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(--currentNos));
}
}
}
How to do this,
You should create interface, and activity implements this interface.
public interface OnItemClick {
void onClick (String value);
}
When you create adapter (last parameter is this interface)
public class MainActivity extends AppCompatActivity implements OnItemClick {
recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData, this);
recyclerView.setAdapter(recycleAdapter);
#Override
void onClick (String value){
// value this data you receive when increment() / decrement() called
}
// In Adapter
private OnItemClick mCallback;
RecycleAdapter(Context context,List<HashMap<String, String>> onlineData,OnItemClick listener){
this.onlineData = onlineData;
this.context = context;
this.mCallback = listener;
}
....
public void increment(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(++currentNos));
mCallback.onClick(quantity.getText().toString());
}
public void decrement(){
int currentNos = Integer.parseInt(quantity.getText().toString()) ;
quantity.setText(String.valueOf(--currentNos));
mCallback.onClick(quantity.getText().toString());
}
I failed to do it with both Interface and Observer pattern. But Local Broadcast worked for me.
In Adapter
String ItemName = tv.getText().toString();
String qty = quantity.getText().toString();
Intent intent = new Intent("custom-message");
// intent.putExtra("quantity",Integer.parseInt(quantity.getText().toString()));
intent.putExtra("quantity",qty);
intent.putExtra("item",ItemName);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Main Activity
public void onCreate(Bundle savedInstanceState) {
...
// Register to receive messages.
// We are registering an observer (mMessageReceiver) to receive Intents
// with actions named "custom-message".
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-message"));
}
...
public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String ItemName = intent.getStringExtra("item");
String qty = intent.getStringExtra("quantity");
Toast.makeText(MainActivity.this,ItemName +" "+qty ,Toast.LENGTH_SHORT).show();
}
};
Three popular ways to solve this problem
Interfaces
Phuoc Huynh has already explained how to use interfaces to solves this.
Observer pattern.
Try googling around observer to understand how it works. We will register the classes who want to receive events with the type of events they want to receive. There will be a manager classes to manage registering and unregistering of receivers and also to send the events to all receivers
public class EventManager {
private static EventManager eventManager;
private static Object syncObject = new Object();
private HashMap<String, ArrayList<EventListener>> listeners = new HashMap<>();
private EventManager(){}
public static EventManager getInstance() {
if (eventManager == null) {
synchronized (syncObject) {
if (eventManager == null) {
eventManager = new EventManager();
}
}
}
return eventManager;
}
public synchronized void registerListener(String event, EventListener listener) {
if (listeners.containsKey(event)) {
listeners.get(event).add(listener);
} else {
ArrayList<EventListener> arrayList = new ArrayList<>();
arrayList.add(listener);
listeners.put(event, arrayList);
}
}
public synchronized void unRegisterListener(String event, EventListener listener) {
if (listeners.containsKey(event)) {
listeners.get(event).remove(listener);
if (listeners.get(event).size() == 0) {
listeners.remove(event);
}
}
}
public void sendEvent(String event, Object o) {
if (listeners.containsKey(event)) {
ArrayList<EventListener> listener = listeners.get(event);
for (EventListener eventListener : listener) {
eventListener.onEvent(o);
}
}
}
}
Your MainActivity will register itself as a receiver of increment and decrement events and also implement onEvent method of IEventListener
public class MainActivity extends AppCompatActivity implements IEventListener{
#Override
protected void onCreate(Bundle onSavedInstanceState) {
EventManager.getInstance().registerEvent("increment", this);
EventManager.getInstance().registerEvent("decrement", this)
}
#Override
public void onEvent(String event) {
if (event.equals("increment") {
//increment
} else if (event.equals("decrement") {
//decrement
}
}
#Override
protected void onDestroy() {
EventManager.getInstance().unRegisterEvent("increment", this);
EventManager.getInstance().unRegisterEvent("decrement", this)
}
}
In you adapter class send the events
EventManager.getInstance().sendEvent("increment");
EventManager.getInstance().sendEvent("decrement");
LocalBroadcasts
LocalBroadcasts works the same way as the above example. you have get Instance of LocalBroadcastManger and send Broadcast on it. Define a broadcast receiver in the onCreate of the activity and register it using registerReceiver() in the Activity. Pass an intent filter in the register receiver with actiontype same as the broadcasts you want your activity to receive. Make sure you unregister the broadcasts whenever you don't need them or in the onDestroy of the activity
Simple solution using interface:
Create an interface with method containing objects/data as parameters:
public interface RecyclerViewDataPass {
public void pass(String productName, String quantity);
}
Implement interface method in Activity & pass it through RecyclerView Adapter:
RecyclerViewDataPass recyclerViewDataPass = new RecyclerViewDataPass() {
#Override
public void pass(String productName, String quantity) {
//we get data from adapter here
//assign parameters to activity variables or do the needed operations
}
};
recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData,recyclerViewDataPass);
recyclerView.setAdapter(recycleAdapter);
Edit adapter's constructor:
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolderRec> {
List<HashMap<String, String>> onlineData;
SQLiteDatabase db;
Context context;
RecyclerViewDataPass recyclerViewDataPass; //here is our data pass object
RecycleAdapter(Context context,List<HashMap<String, String>> onlineData, RecyclerViewDataPass recyclerViewDataPass){
this.onlineData = onlineData;
this.context=context;
this.recyclerViewDataPass=recyclerViewDataPass; //get data pass object from activity
}
Inside RecyclerView Adapter call pass function to send data to activity:
recyclerViewDataPass.pass(tv.getText().toString(), quantity.getText().toString());
Check out this. It works for me.
Just Paste in Your Activity or Fragment
rvSelectedProductList = Recyclerview
selcetedItemAdapter = RecyclerView Adapter
rvSelectedProductList.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final int itemCount = selectedItemAdapter.getItemCount();
for (int i = 0; i < itemCount; i++) {
TextView tvSelling = rvSelectedProductList.getChildAt(i).findViewById(R.id.tvSelling);
TextView textViewDrawerTitle = rvSelectedProductList.getChildAt(i).findViewById(R.id.tvCartQty);
String totalamount = tvSelling.getText().toString();
String qty = textViewDrawerTitle.getText().toString();
System.out.println("qty" + qty);
System.out.println("total" + totalamount);
}
rvSelectedProductList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
//Simply it works for me
//In onBindViewHolder of RecyclerAdapter write the following code on clickEvent of any view;
Intent intent = new Intent(tContext, TargetActivity.class);
intent.putExtra("key", "value");
tContext.startActivity(intent);
//TargetActivity.java
String str = getIntent().getStringExtra("key");
//You got the value as String :)
add these codes in onBindViewHolder
Intent intent = new Intent("message_subject_intent");
intent.putExtra("name" , String.valueOf(messageSubject.getname()));
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Add on MainActivity
public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String name= intent.getStringExtra("name");
Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,new IntentFilter("message_subject_intent"));
I am trying to get the image string from the recyclerview, that is already populated, so that I can display the image on the imageview of another activity. Here, I get the path(url) of image using jsoup:
org.jsoup.nodes.Document document = Jsoup.connect(URL).get();
for(Element e : document.select("img[src]"))
{
Elements imgScr = e.select("img[src]");
String elements = imgScr.attr("src");
String text = imgScr.attr("alt");
String desc = imgScr.attr("title");
arrayList.add(new FeedItem(text, elements, desc));
}
into elements variable and then storing it into arraylist. I want to get that path(url) of image(stored in elements) so that I can display that image in another activity. I tried to retrieve that url from the arrayList using this method:
public String getImageUrl(int pos)
{
return arrayList.get(pos).getThumb();
}
but a IndexOutOfBound exception is thrown, saying that the index(pos) is invalid and size of arrayList is 0. I don't know why it is saying that the list has size 0, while the Recyclerview gets pouplated and shows the data which I parsed using jsoup. Please help me out guys, I am stuck on this for three days.
Okay the complete code is here:
This the main activity which shows the recyclerview
public class RestaurantsAndCafesActivity extends Activity {
public static final String URL = "http://192.168.8.102:80/jay.html";
private RecyclerView mRecyclerView;
private RCRecyclerAdapter adapter;
public String imgUrl;
//public List<FeedItem> feedItemList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reyclerview_layout);
/* Initialize RecyclerView */
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//parseResult();
new getDataAsyncTask().execute();
final GestureDetector mGestureDetector = new GestureDetector(RestaurantsAndCafesActivity.this, new GestureDetector.SimpleOnGestureListener() {
#Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
View child = recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());
if(child!=null && mGestureDetector.onTouchEvent(motionEvent)){
Toast.makeText(RestaurantsAndCafesActivity.this,"Clicked Number "+recyclerView.getChildPosition(child), Toast.LENGTH_SHORT).show();
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child));
Intent intent = new Intent(RestaurantsAndCafesActivity.this, GetReviewActivity.class);
intent.putExtra("Imgurl" ,imgUrl);
startActivity(intent);
return true;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
});
}
public class getDataAsyncTask extends AsyncTask<Void,Void,Void>{
ArrayList<FeedItem> arrayList = new ArrayList<>();
public String getImageUrl(int pos)
{
return arrayList.get(pos).getThumb();
}
#Override
protected Void doInBackground(Void... params) {
try {
org.jsoup.nodes.Document document = Jsoup.connect(URL).get();
for(Element e : document.select("img[src]"))
{
Elements imgScr = e.select("img[src]");
String elements = imgScr.attr("src");
String text = imgScr.attr("alt");
String desc = imgScr.attr("title");
arrayList.add(new FeedItem(text, elements, desc));
}
}
catch(IOException e)
{
e.printStackTrace();
}
return null;
}
ProgressDialog progressDialog;
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(RestaurantsAndCafesActivity.this,"Loading","Please Wait",true,false);
}
#Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
adapter = new RCRecyclerAdapter(getApplicationContext(),arrayList);
mRecyclerView.setAdapter(adapter);
}
}
}
These are the adapter, viewholder and data classes:
public class RCRecyclerAdapter extends RecyclerView.Adapter<RCRecyclerViewListRowHolder> {
private List<FeedItem> feedItemList;
private Context mContext;
public RCRecyclerAdapter(Context context, List<FeedItem> feedItemList) {
this.feedItemList = feedItemList;
this.mContext = context;
}
#Override
public RCRecyclerViewListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.restaurants_cafes_layout_card, null);
RCRecyclerViewListRowHolder mh = new RCRecyclerViewListRowHolder(v);
return mh;
}
#Override
public void onBindViewHolder(RCRecyclerViewListRowHolder RCRecyclerViewListRowHolder, int i){
FeedItem feedItem = feedItemList.get(i);
Picasso.with(mContext).load(feedItem.getThumb()
).error(R.drawable.placeholder).placeholder(R.drawable.placeholder).into(RCRecyclerViewListRowHolder.thumbnail);
RCRecyclerViewListRowHolder.title.setText(feedItemList.get(i).title);
RCRecyclerViewListRowHolder.desc.setText(feedItemList.get(i).desc);
}
#Override
public int getItemCount() {
return (null != feedItemList ? feedItemList.size() : 0);
}
}
viewholder:
public class RCRecyclerViewListRowHolder extends RecyclerView.ViewHolder {
public ImageView thumbnail;
public TextView title;
public TextView desc;
//Context context;
public RCRecyclerViewListRowHolder(View view) {
super(view);
this.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
this.title = (TextView) view.findViewById(R.id.title);
this.desc = (TextView) view.findViewById(R.id.desc);
}
}
data:
public class FeedItem {
public String title;
public String thumb;
public String desc;
public FeedItem(String title, String thumb , String desc) {
this.title = title;
this.thumb = thumb;
this.desc = desc;
}
public String getThumb() {
return thumb;
}
}
Here is the culprit:
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child));
You're actually creating a new AsyncTask - if you try to get an element from the arrayList inside that new AsyncTask it's obvious the list is empty, because task populates the list within its doInBackground() method, and it hasn't been executed.
Solution:
In your onCreate method, create your getDataAsyncTask and keep a reference to it in a member variable.
Then, when the task finishes its execution and calls onPostExecute(Void aVoid) set a flag indicating that fact.
Next, in your onClickListener, reference the same task, but execute the code only if the asyncTaskFinished flag is set to true:
public class RestaurantsAndCafesActivity extends Activity {
public static final String URL = "http://192.168.8.102:80/jay.html";
private RecyclerView mRecyclerView;
private RCRecyclerAdapter adapter;
public String imgUrl;
//public List<FeedItem> feedItemList;
private getDataAsyncTask myAsyncTask;
private volatile boolean asyncTaskFinished = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reyclerview_layout);
/* Initialize RecyclerView */
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//parseResult();
myAsyncTask = new getDataAsyncTask();
myAsyncTask.execute();
...
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
View child = recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());
if(child!=null && mGestureDetector.onTouchEvent(motionEvent)){
if(asyncTaskFinished) {
Toast.makeText(RestaurantsAndCafesActivity.this,"Clicked Number "+recyclerView.getChildPosition(child), Toast.LENGTH_SHORT).show();
imgUrl = myAsyncTask.getImageUrl(recyclerView.getChildPosition(child));
Intent intent = new Intent(RestaurantsAndCafesActivity.this, GetReviewActivity.class);
intent.putExtra("Imgurl" ,imgUrl);
startActivity(intent);
return true;
}
return false;
}
}
In AsyncTask:
#Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
adapter = new RCRecyclerAdapter(getApplicationContext(),arrayList);
mRecyclerView.setAdapter(adapter);
asyncTaskFinished = true;
}
Please note that it is a solution that makes minimal changes in your existing code, however i would suggest a different approach - keeping the list in AsyncTask is kinda ugly, better way is to return it from doInBackground, and within onPostExecute, pass it to adapter (while not keeping a class-scope reference to it in the task), and when you need to access an element fromn the list, just reference the adapter, not your AsyncTask:
imgUrl = adapter.getList().get(recyclerView.getChildPosition(child)).getThumb();
I am newbie to Android apps development.
I have a class, which contains RecyclerView.
public class ScreenOne extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private RecyclerView mRecyclerView;
private FilmSetAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
SwipeRefreshLayout mSwipeRefreshLayout;
RequestTask requestTask;
ArrayList<Film> listOfFilms;
ArrayList<Cinema> listOfCinemas;
ArrayList<String> cityIDs;
public ScreenOne() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.screen_one, container,
false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(getActivity());
//mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManager);
//mRecyclerView.setItemAnimator(new DefaultItemAnimator());
listOfFilms = new ArrayList<>();
mAdapter = new FilmSetAdapter(listOfFilms);
mRecyclerView.setAdapter(mAdapter);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorScheme(R.color.blue, R.color.cyan, R.color.grey_blue, R.color.lightblue);
try {
updateFilms();
} catch (InterruptedException e) {
e.printStackTrace();
}
return rootView;
}
private void updateFilms() throws InterruptedException {
requestTask = new RequestTask();
try {
requestTask.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
private boolean isNetworkConnected() {
ConnectivityManager cm =
(ConnectivityManager) getActivity().getSystemService(getActivity().CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
#Override
public void onRefresh() {
Toast.makeText(getActivity(), R.string.refresh_started, Toast.LENGTH_SHORT).show();
mSwipeRefreshLayout.setRefreshing(true);
mAdapter.setDataset(new ArrayList<Film>());
mAdapter.notifyDataSetChanged();
try {
updateFilms();
} catch (InterruptedException e) {
e.printStackTrace();
}
DatabaseHandler database = new DatabaseHandler(getActivity());
mAdapter = new FilmSetAdapter(database.getAllFilms());
mRecyclerView.swapAdapter(mAdapter, false);
database.close();
mSwipeRefreshLayout.postDelayed(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(getActivity(), R.string.refresh_finished, Toast.LENGTH_SHORT).show();
}
}, 3000);
}
class RequestTask extends AsyncTask<Void, Void, Void> {
protected void getPreferenciesCity()
{
cityIDs = new ArrayList<>();
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
Set<String> selections = sharedPrefs.getStringSet("cities", null);
try {
Log.d("SHARED PREFERENCES CITY", selections.toString());
cityIDs.addAll(selections);
}catch (NullPointerException e){Log.d("SHARED PREFERENCES CITY", "SP are empty");}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
listOfFilms = new ArrayList<>();
getPreferenciesCity();
}
#Override
protected Void doInBackground(Void... params) {
if(isNetworkConnected()) {
DatabaseHandler database = new DatabaseHandler(getActivity());
database.clearFilms();
try {
HttpHandler httpHandler = new HttpHandler();
listOfFilms = new ArrayList<>(httpHandler.listOfFilmsRequest(cityIDs));
listOfCinemas = new ArrayList<>(httpHandler.listOfCinemasRequest());
Film film;
Cinema cinema;
for (Iterator<Film> filmiterator = listOfFilms.iterator(); filmiterator.hasNext(); ) {
film = filmiterator.next();
if (database.isInDatabase(film.getID()))
database.updateFilm(film);
else
database.addFilm(film);
}
for (Iterator<Cinema> cinemaiterator = listOfCinemas.iterator(); cinemaiterator.hasNext(); ) {
cinema = cinemaiterator.next();
if (database.CinemaIsInDatabase(cinema.getIDCinema()))
database.updateCinema(cinema);
else
database.addCinema(cinema);
}
database.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
DatabaseHandler database = new DatabaseHandler(getActivity());
mAdapter.setDataset(database.getAllFilms());
mAdapter.notifyDataSetChanged();
}
}
}
It executes a method, which is placed in the AsyncTask class. This method downloads data from server, puts it to database first and after that sets the recycler view adapter. The problem is that sometimes text data are changed while scrolling it. See attached video.
Code of adapter is:
public class FilmSetAdapter extends RecyclerView.Adapter<FilmSetAdapter.ViewHolder>{
private ArrayList<Film> mDataset;
final static String LOG_TAG = "FilmSetAdapter";
public void setDataset(ArrayList<Film> allFilms) {
mDataset = new ArrayList<>(allFilms);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public static TextView filmTitle;
public TextView country;
public TextView ticketsFrom;
public TextView rating;
public TextView format;
public ImageView poster;
public int id;
public ViewHolder(final View itemView) {
super(itemView);
filmTitle = (TextView) itemView.findViewById(R.id.filmtitle);
country = (TextView)itemView.findViewById(R.id.country);
ticketsFrom = (TextView) itemView.findViewById(R.id.ticketsfrom);
rating = (TextView)itemView.findViewById(R.id.rating);
poster = (ImageView) itemView.findViewById(R.id.poster);
format = (TextView) itemView.findViewById(R.id.format);
format.setTypeface(null, Typeface.BOLD_ITALIC);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cardview, parent, false);
final ViewHolder vh = new ViewHolder(v);
v.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
Log.d(LOG_TAG, "Нажата карточка. Вызов из activity "+v.toString());
Intent intent = new Intent(v.getContext(),FilmInfoActivity.class);
intent.putExtra("EXTRA_FILM_ID", vh.id);
v.getContext().startActivity(intent);
}
});
return vh;
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.filmTitle.setText(mDataset.get(position).getTitle().toString()+" ID="+mDataset.get(position).getID()+" POS="+position);
holder.country.setText(mDataset.get(position).getCountry());
holder.ticketsFrom.setText(holder.ticketsFrom.getContext().getString(R.string.tickets_from) +
mDataset.get(position).getRating().toString());
holder.rating.setText(holder.rating.getContext().getString(R.string.rating_kinopoisk) +
mDataset.get(position).getRating());
holder.id = mDataset.get(position).getID();
holder.format.setText(mDataset.get(position).getFormat());
Picasso.with(holder.poster.getContext()).
load(mDataset.get(position).getPoster()).
skipMemoryCache().
into(holder.poster);
}
#Override
public int getItemCount() {
if(mDataset != null)
return mDataset.size();
return 0;
}
public FilmSetAdapter(ArrayList<Film> myDataset) {
mDataset = new ArrayList<>(myDataset);
}
}
I have no clue on how to sort it out.
it seem to that there is a typo mistake in your code, look at that, you have in your ViewHolder:
public static TextView filmTitle;
But then you work with it like with your other fields:
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.filmTitle.setText(mDataset.get(position).getTitle() + ...);
...
}
A little advice for you as a newbie: just.. pay more attention to your code, and you'll be fine in programming :)