I am trying to use RssReader using a feedparser library. It is working fine on android M & N but it crashes on versions L and below.
here is what i have done
ReadRss readRss = new ReadRss(this, recyclerView);
isNetworkAvailable();
if (isNetworkAvailable()) {
readRss.execute();
} else {
Toast.makeText(getBaseContext(), "Couldn't connect to Internet.", Toast.LENGTH_LONG).show();
}
ReadRss is as follows
class ReadRss extends AsyncTask<Void, Void, Void> {
Context context;
private ProgressDialog progressDialog;
private ArrayList<FeedItem> feedItems;
private RecyclerView recyclerView;
ReadRss(Context context, RecyclerView recyclerView) {
this.recyclerView = recyclerView;
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
}
#Override
protected void onPreExecute() {
progressDialog.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
RssAdapter adapter = new RssAdapter(context, feedItems);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new VerticalSpace(50));
recyclerView.setAdapter(adapter);
}
#Override
protected Void doInBackground(Void... params) {
ProcessXml(Getdata());
return null;
}
private void ProcessXml(Document data) {
try {
URL url = new URL("http:pockettanksnews.blogspot.com/feeds/posts/default");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream feedStream = httpConnection.getInputStream();
FeedParser parser = FeedParserFactory.newParser();
System.out.println("success");
Feed feed = parser.parse(feedStream);
feedItems=new ArrayList<>();
for (Item i : feed.getItemList()) {
FeedItem item=new FeedItem();
System.out.println(i.getTitle());
item.setTitle(i.getTitle());
System.out.println(i.getLink());
item.setLink(i.getLink());
System.out.println(i.getPubDate());
item.setPubDate(i.getPubDate().toString());
item.setThumbnailUrl("https:1079638729.rsc.cdn77.org/androidgame_img/pocket_tanks/real/1_pocket_tanks.jpg");
item.setDescription(i.getDescription());
feedItems.add(item);
}
} else {
System.out.println("error");
}
}
catch (Exception except){
;
}
}
private Document Getdata() {
try {
String address = "http://pockettanksnews.blogspot.com/feeds/posts/default/-/pttipsyoutube/?alt=rss";
URL url = new URL(address);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDoc = builder.parse(inputStream);
return xmlDoc;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
and my RssAdapter is as below
public class RssAdapter extends RecyclerView.Adapter<RssAdapter.MyViewHolder> {
ArrayList<FeedItem> feedItems=new ArrayList<FeedItem>();
Context context;
public RssAdapter(Context context, ArrayList<FeedItem> feedItems) {
this.feedItems = feedItems;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.custum_row_news_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
FeedItem current = feedItems.get(position);
holder.Title.setText(current.getTitle());
holder.Description.loadDataWithBaseURL("", current.getDescription(), "text/html", "UTF-8", "");
holder.Date.setText(current.getPubDate());
}
#Override
public int getItemCount() {
return feedItems.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView Title, Date;
WebView Description;
ImageView Thumbnail;
CardView cardView;
public MyViewHolder(View itemView) {
super(itemView);
Title = (TextView) itemView.findViewById(R.id.title_text);
Description = (WebView) itemView.findViewById(R.id.description_text);
Description.getSettings().setJavaScriptEnabled(true);
Date = (TextView) itemView.findViewById(R.id.date_text);
Thumbnail = (ImageView) itemView.findViewById(R.id.thumb_img);
cardView = (CardView) itemView.findViewById(R.id.cardview);
}
}
The app crashes on getItemCount method. It shows Null Pointer Exception : Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference.
In case of error your feeds will become null. So change your code and handle it.
// Add null check here.
if(feedItems!= null) {
RssAdapter adapter = new RssAdapter(context, feedItems);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new VerticalSpace(50));
recyclerView.setAdapter(adapter);
} else {
// Show some error
}
Another way to handle this null pointer is add null check inside Adapter.
public RssAdapter(Context context, ArrayList<FeedItem> feedItems) {
if(feedItems!= null) {
this.feedItems.addAll(feedItems);
}
this.context = context;
}
Then try to find out exception if any in getting data from server. I believe only Getdata() method is responsible for that.
Related
//This is where the codes start actually.I want to open an activity from a listOnclick listner i have tried alot but i was not able to set the listners can someone please help me here i am i new bee
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
lvMovies = findViewById(R.id.lvMovies);
}
this is where i starts the Jsontask
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_dry_clean:
new JSONTask().execute("");
return true;
case R.id.press:
new JSONTask().execute("https:/");
return true;
}
return false;
}
};
this is where AsyncTask starts.
public class JSONTask extends AsyncTask<String, String, List<MovieModel>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog.show();
}
#Override
protected List<MovieModel> doInBackground(String... params) {
BufferedReader reader = null;
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(params[0]);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
InputStream stream = httpURLConnection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentobject = new JSONObject(finalJson);
JSONArray parentarray = parentobject.getJSONArray("movies");
List<MovieModel> movieModelList = new ArrayList<>();
for (int i = 0; i < parentarray.length(); i++) {
JSONObject finalObject = parentarray.getJSONObject(i);
MovieModel movieModel = new MovieModel();
movieModel.setClothesname(finalObject.getString("clothesname"));
movieModel.setPrice(finalObject.getInt("price"));
movieModel.setImage(finalObject.getString("image"));
///adding the final object in the list*/
movieModelList.add(movieModel);
}
return movieModelList;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (httpURLConnection != null)
httpURLConnection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(List<MovieModel> result) {
super.onPostExecute(result);
dialog.dismiss();
MovieAdapter adapter = new MovieAdapter(getApplicationContext(), R.layout.row, result);
lvMovies.setAdapter(adapter);
}
}
// this is the adapter
public class MovieAdapter extends ArrayAdapter {
private List<MovieModel> movieModelList;
private int resource;
private LayoutInflater inflater;
public MovieAdapter(Context context, int resource, List<MovieModel> objects) {
super(context, resource, objects);
movieModelList = objects;
this.resource = resource;
inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, #Nullable View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(resource, null);
holder.tvMovie = convertView.findViewById(R.id.clothes_name);
holder.tvYear = convertView.findViewById(R.id.price);
holder.ivMovieIcon = convertView.findViewById(R.id.list_view_icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Do you want to start a new activity when an item in listview clicked?
you can use holder.setOnClickListener
otherwise, give us more details about what you want
you can use this code for RecyclerView adapter
public class MovieAdapterextends RecyclerView.Adapter<MovieAdapter.OrderHolder> {
private List<MovieModel> movieModelList;
private int resource;
private LayoutInflater inflater;
public MovieAdapter(Context context, int resource, List<MovieModel> objects) {
super(context, resource, objects);
movieModelList = objects;
this.resource = resource;
inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
}
#Override
public OrderHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_video, parent, false);
return new OrderHolder(view);
}
#Override
public void onBindViewHolder(final OrderHolder holder, final int position) {
VideoObject videoObject = list.get(position);
//put your code here to set text for textview like that
holder.txvTitle.setText(videoObject.getVideo_title());
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playVideo(videoObject.getVideo_code(), videoObject.getVideo_image());
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//write your code to start activity
Intent intent=new Intent(context,YOUR_ACTIVITY.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public class OrderHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView clothes_name;
private TextView clothes_name;
private ImageView list_view_icon;
OrderHolder(View itemView) {
super(itemView);
clothes_name= itemView.findViewById(R.id.clothes_name);
price= itemView.findViewById(R.id.price);
list_view_icon= itemView.findViewById(R.id.list_view_icon);
}
#Override
public void onClick(View view) {
}
}
}
I'm trying to fetch data from a JSON, but it doesn't seem to work. OnBindViewHolder is never called...
ADAPTER CODE:
public class AdapterRallye extends RecyclerView.Adapter<AdapterRallye.MyViewHolder> implements View.OnClickListener {
private Context context;
private View.OnClickListener listener;
private List<DataRallye> data;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView Rallye_Nom;
public ImageView Rallye_Foto;
public TextView Rallye_Provincia;
public TextView Rallye_DataI;
public TextView Rallye_Tipus;
// create constructor to get widget reference
public MyViewHolder(final View itemView) {
super(itemView);
Rallye_Nom = (TextView) itemView.findViewById(R.id.tv_nom);
Rallye_Foto = (ImageView) itemView.findViewById(R.id.iv_foto);
Rallye_Provincia = (TextView) itemView.findViewById(R.id.tv_provincia);
Rallye_DataI = (TextView) itemView.findViewById(R.id.tv_datai);
Rallye_Tipus = (TextView) itemView.findViewById(R.id.tv_tipus);
}
}
// create constructor to innitilize context and data sent from MainActivity
public AdapterRallye(List<DataRallye> dadesrally) {
this.data = dadesrally;
}
// Inflate the layout when viewholder created
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.container_rallye, parent, false);
view.setOnClickListener(this);
return new MyViewHolder(view);
}
// Bind data
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// Get current position of item in recyclerview to bind data and assign values from list
DataRallye current = data.get(position);
holder.Rallye_Nom.setText(current.getRallyeNom());
holder.Rallye_Tipus.setText(current.getRallyeTipus());
holder.Rallye_DataI.setText(current.getRallyeDataI());
holder.Rallye_Provincia.setText(current.getRallyeProvincia());
holder.Rallye_Provincia.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
// load image into imageview using glide
Glide.with(context).load("http://rallyecat.esy.es/fotos/" + current.getRallyeFoto())
.placeholder(R.drawable.rallyecatlogo)
.error(R.drawable.rallyecatlogo)
.into(holder.Rallye_Foto);
}
public void setOnClickListener(View.OnClickListener listener) {
this.listener = listener;
}
#Override
public void onClick(View view) {
if (listener != null)
listener.onClick(view);
}
// return total item from List
#Override
public int getItemCount() {
return data.size();
}
}
FRAGMENT CODE:
public class FragmentRally extends Fragment {
public FragmentRally() {
// Required empty public constructor
}
private List<DataRallye> llistarallyes = new ArrayList<>();
private RecyclerView recyclerView;
private AdapterRallye mAdapter;
private Intent intent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_fragment_rally, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.llistarallyes);
mAdapter = new AdapterRallye(llistarallyes);
recyclerView.setAdapter(mAdapter);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
new AsyncFetch().execute();
mAdapter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
intent = new Intent(getActivity(), ActivitatDetalls.class);
intent.putExtra("nombarra", llistarallyes.get(recyclerView.getChildAdapterPosition(view)).getRallyeNom());
startActivity(intent);
}
});
return rootView;
}
// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private class AsyncFetch extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(getActivity());
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tCarregant...");
pdLoading.setCancelable(false);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
// Enter URL address where your json file resides
// Even you can make call to php file which returns json llistarallyes
url = new URL("http://www.rallyecat.esy.es/Obtenir_events.php");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive llistarallyes from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
// setDoOutput to true as we recieve llistarallyes from json file
//conn.setDoOutput(true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read llistarallyes sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line + "\n");
}
// Pass llistarallyes to onPostExecute method
return (result.toString());
} else {
Toast.makeText(getActivity(), "No hi ha connexió a internet.",
Toast.LENGTH_LONG).show();
return ("No hi ha connexió a internet.");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
pdLoading.dismiss();
try {
JSONArray jArray = new JSONArray(result);
// Extract llistarallyes from json and store into ArrayList as class objects
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
DataRallye dadesrallye = new DataRallye();
dadesrallye.setRallyeNom(json_data.getString("nom"));
dadesrallye.setRallyeTipus(json_data.getString("tipus"));
dadesrallye.setRallyeDataI(json_data.getString("datai"));
dadesrallye.setRallyeProvincia(json_data.getString("provincia"));
dadesrallye.setRallyeFoto(json_data.getString("foto"));
llistarallyes.add(dadesrallye);
}
} catch (JSONException e) {
Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_LONG).show();
}
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.fragment_fragment_rally, parent, false));
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), ActivitatDetalls.class);
context.startActivity(intent);
}
});
}
}
}
I've seen other StackOverflow posts where the problem is already solved, but I've been trying alot of the solutions the user said, but none is working...
Thanks!
Try to call mAdapter.notifyDataSetChanged(); in onPostExecute() method.
You need to notify your adapter after you made changes.
if i write this code in a class extends AppCompatActivity it
works but in a fragment class i don't know why it doesn't work .
in the activity that has this fragment i use another adapter
to show products with the same code and it works
public class Categroy extends Fragment{
// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
public RecyclerView mRVcategoryList;
public AdapterCategory mAdapter;
private String myurl="http://10.0.3.2/mobilaApp/category.php";
// private String categoryurl="http://10.0.3.2/mobilaApp/category.php";
public LinearLayoutManager layoutManager;
List<DataCategory> data=new ArrayList<>();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// execute asyncLogin
new AsyncLogin().execute();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_categroy, container, false);
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.rvcat);
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// 3. create an adapter
AdapterCategory mAdapter = new AdapterCategory(getActivity().getApplicationContext(), data);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
return rootView;
}
private class AsyncLogin extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(getActivity());
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
// Enter URL address where your json file resides
// Even you can make call to php file which returns json data
url = new URL(myurl);
// urlcat = new URL(categoryurl);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive data from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
// setDoOutput to true as we recieve data from json file
conn.setDoOutput(true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
// Pass data to onPostExecute method
return (result.toString());
} else {
return ("unsuccessful");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
// dississ dialog pdLoading.dismiss();
pdLoading.dismiss();
try {
JSONArray jArray = new JSONArray(result);
// Extract data from json and store into ArrayList as class objects
for(int i=0;i<jArray.length();i++){
JSONObject json_data = jArray.getJSONObject(i);
DataCategory categorydata = new DataCategory();
categorydata.name_cat= json_data.getString("name_cat");
data.add(categorydata);
}
mRVcategoryList = (RecyclerView)getActivity(). findViewById(R.id.rvcat);
mAdapter = new AdapterCategory(getActivity().getApplicationContext(), data);
mRVcategoryList.setAdapter(mAdapter);
mRVcategoryList.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
} catch (JSONException e) {
Toast.makeText(getActivity().getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
/* if i write this code in a class extends AppCompatActivity it
works but in a fragment class i don't know why it doesn't work .
in the activity that has this fragment i use another adapter
to show products with the same code and it works
*/
Adapter is here
public AdapterCategory(Context context, List<DataCategory> data){
this.context=context;
inflater= LayoutInflater.from(context);
this.data=data;
}
// Inflate the layout when viewholder created
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=inflater.inflate(R.layout.categoryrow, parent,false);
MyHolder holder=new MyHolder(view);
return holder;
}
// Bind data
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// Get current position of item in recyclerview to bind data and assign values from list
MyHolder myHolder= (MyHolder) holder;
DataCategory current=data.get(position);
myHolder.namecat.setText(current.name_cat);
}
// return total item from List
#Override
public int getItemCount() {
return data.size();
}
class MyHolder extends RecyclerView.ViewHolder{
TextView namecat;
// TextView textPrice;
// create constructor to get widget reference
public MyHolder(View itemView) {
super(itemView);
namecat= (TextView) itemView.findViewById(R.id.category_name);
}
}
}
Set layoutManager to your recyclerView using getContext() instead of getActivity() and it will work.
mListLayoutManager=new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mListLayoutManager);
Thank you all
the problem was to replace getActivity() by getView() onpostexecute
mRVFishPrice = (RecyclerView)getView().findViewById(R.id.fishPriceList);
mAdapter = new AdapterFish(getActivity(), data);
mRVFishPrice.setAdapter(mAdapter);
mRVFishPrice.setLayoutManager(new LinearLayoutManager(getActivity()));
I have a button inside CardView which represents item of RecycleView. I've managed to handle the click event inside the ViewHolder class but I need to call function on MainActivity, How can I implement that with below code?
My code as below
ShopItemRecyclerViewAdapter.java
public class ShopItemRecyclerViewAdapter extends RecyclerView.Adapter<ShopItemRecyclerViewAdapter.ListItemViewHolder> {
static ArrayList<ShopListItemModel> list;
LayoutInflater inflater;
public ShopItemRecyclerViewAdapter(ArrayList<ShopListItemModel> list, Context context){
inflater = LayoutInflater.from(context);
this.list = list;
}
public ListItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.list_item, parent , false);
ListItemViewHolder vh = new ListItemViewHolder(view);
return vh;
}
public void onBindViewHolder(ListItemViewHolder holder, int position) {
ShopListItemModel current = list.get(position);
holder.name.setText(current.getName());
holder.price.setText(String.valueOf(current.getPrice()));
}
public int getItemCount() {
return list.size();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
TextView name;
TextView price;
ImageButton btnDelete;
ListItemViewHolder(final View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cvShopListItem);
name = (TextView)itemView.findViewById(R.id.name);
price = (TextView)itemView.findViewById(R.id.price);
btnDelete = (ImageButton)itemView.findViewById(R.id.btnDeleteItem);
itemView.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//here i can handle the click but i think i need to use it in the main activity
}
}
}
MainActivity.java (skipped irrelevent code)
public class ShopCartScreen extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
RecyclerView cartItems; //recycler to hold the cart list
ArrayList<ShopListItemModel> list = new ArrayList<ShopListItemModel>();
ShopItemRecyclerViewAdapter adapter;
GetShopingCartList getShopingCartList; ////instance of network operation class to retrieve shop cart items list from server data base
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shop_carts_list);
cartItems = (RecyclerView) findViewById(R.id.newListItem);
cartItems.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
cartItems.setLayoutManager(llm)
}
public void bindData(int listNumber) {
getShopingCartList = new GetShopingCartList(this, list, adapter, cartItems, listNumber, totalPrice);
getShopingCartList.execute("link to query which returns json object");
}
}
GetShopingCartList.java for network operation
public class GetShopingCartList extends AsyncTask<String, String, ArrayList<ShopListItemModel>> {
private ArrayList<ShopListItemModel> shopCartItemList;
Context context;
RecyclerView items;
ShopItemRecyclerViewAdapter adapter;
int listNumber;
public GetShopingCartList(Context context, ArrayList<ShopListItemModel> shopCartItemList, ShopItemRecyclerViewAdapter adapter,
RecyclerView items ,int listNumber) {
this.context = context;
this.shopCartItemList = shopCartItemList;
this.adapter = adapter;
this.items = items;
this.listNumber = listNumber;
}
protected ArrayList<ShopListItemModel> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
shopCartItemList = new ArrayList<ShopListItemModel>();
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("result");
for (int i = 0; i < parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);//get the cuttent json object which is representaion of shop cart model object
String name = finalObject.getString("name");
String price = finalObject.getString("price");
Double d = Double.parseDouble(price);
ShopListItemModel item = new ShopListItemModel(name, d);
shopCartItemList.add(item);//adds the shopcart to the list of shop carts model
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return shopCartItemList;
}
protected void onPostExecute(ArrayList<ShopListItemModel> s) {
super.onPostExecute(s);
adapter = new ShopItemRecyclerViewAdapter(shopCartItemList, context);
items.setAdapter(adapter);
}
public ArrayList<ShopListItemModel> getList() {
return shopCartItemList;
}
}
Implement a method inside ShopCartScreen.java, then you can use the context object inside the adapter.
((ShopCartScreen)context).methodImplemented(ShopListItemModel model)
//add this code inside onClick event of the button
ok this is my solution if anyone needs it (i combined 2 methods/ 1 in the main activity and 1 in the recycler adapter):
in my recycler adapter i added this delete method:
//delete the item from the recycler Immediately for user interaction
public void delete(int position){
list.remove(position);
notifyItemRemoved(position);
}
in my ViewHolder class:
ListItemViewHolder(final View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cvShopListItem);
name = (TextView)itemView.findViewById(R.id.name);
price = (TextView)itemView.findViewById(R.id.price);
btnDelete = (ImageButton)itemView.findViewById(R.id.btnDeleteItem);
itemView.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
#Override
public void onClick(View v) {
((ShopCartScreen)context).deleteItem(getPosition());//calls method in main activity
delete(getPosition());
}
and in the main activity:
public void deleteItem(int postion){
list = getShopingCartList.getList();
ShopListItemModel tmp = list.get(postion);
tmp.getName(); //gets the item name to remove
shopCartModel.getNumber(); //gets the cart number for deleting the item for the correct cart
new DeleteCartItem(this , shopCartModel , tmp).execute(); //remove the item from the data base
}
I'm new in recycle view. Tthis is sample code for my RecycerView. I'm getting data from internet and in onPostExecute() I set the adapter.
RecyclerView recycle;
MyAdapter adapters;
private static String url;
private static final String TAG_CONTACTS = "contacts";
JSONArray contacts = null;
ProgressDialog pDialog;
private int preLast;
int page = 0, in, to;
Boolean loadmore = true;
HashMap<String, String> item;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
url = "http://192.168.1.20/adres/getAds.php";
recycle = (RecyclerView) findViewById(R.id.recycle);
recycle.setItemAnimator(new DefaultItemAnimator());
new GetContacts().execute();
final GestureDetector mGestureDetector = new GestureDetector(MainActivity.this, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
private class GetContacts extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {
Boolean goterr = false;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected ArrayList<HashMap<String, String>> doInBackground(Void... arg0) {
String jsonStr = Fun.getHtml(url);
Log.v("this", jsonStr);
ArrayList<HashMap<String, String>> dataC = new ArrayList<HashMap<String, String>>();
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
contacts = jsonObj.getJSONArray(TAG_CONTACTS);
if (contacts.length() < 20)
loadmore = false;
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
HashMap<String, String> contact = new HashMap<String, String>();
contact.put("id", new String(c.getString("id").getBytes("ISO-8859-1"), "UTF-8"));
contact.put("name", new String(c.getString("name").getBytes("ISO-8859-1"), "UTF-8"));
dataC.add(contact);
dataC.add(contact);
}
} catch (JSONException e) {
Log.v("this", e.getMessage());
goterr = true;
} catch (UnsupportedEncodingException e) {
Log.v("this", e.getMessage());
goterr = true;
}
} else {
goterr = true;
}
return dataC;
}
#Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
super.onPostExecute(result);
if (pDialog.isShowing() && pDialog != null)
pDialog.dismiss();
if (!isCancelled() && goterr == false && result != null) {
if (adapters == null) {
adapters = new MyAdapter(MainActivity.this, result);
recycle.setAdapter(adapters);
recycle.setLayoutManager(new LinearLayoutManager(MainActivity.this));
} else {
adapters.addAll(result);
}
} else {
//MyToast.makeText(MainActivity.this, DariGlyphUtils.reshapeText(MainActivity.this.getResources().getString(R.string.problemload)));
}
}
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private LayoutInflater inflater;
public ArrayList<HashMap<String, String>> list;
public MyAdapter(Context context, ArrayList<HashMap<String, String>> list) {
inflater = LayoutInflater.from(context);
this.list = list;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parrent, int i) {
View view = inflater.inflate(R.layout.customrow, parrent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
public void addAll(ArrayList<HashMap<String, String>> result) {
if (this.list == null) {
this.list = result;
} else {
this.list.addAll(result);
}
notifyDataSetChanged();
}
public HashMap<String, String> geting(int position) {
return list.get(position);
}
#Override
public void onBindViewHolder(MyViewHolder viewHolder, int position) {
item = list.get(position);
viewHolder.txt.setText(item.get("onvan"));
}
#Override
public int getItemCount() {
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView txt;
ImageView img;
public MyViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txt = (TextView) itemView.findViewById(R.id.txt);
img = (ImageView) itemView.findViewById(R.id.img);
}
#Override
public void onClick(View v) {
item = adapters.geting(getPosition());
Log.v("this", "id " + item.get("id"));
/*Intent in=new Intent (FistActiivty.this,AdDetails.class);
in.putExtra("ad_id",item.get("id"));
startActivity(in)*/
;
}
}
}
after I run it , I get this error :
RecyclerView﹕ No adapter attached; skipping layout
what is wrong with this code ?
The problem is that during the first layout pass, while your AsyncTask is still fetching data from the network, your RecyclerView has not adapter.
You can instead attach the (empty) adapter in onCreate() and update the adapter's data in your onPostExecute(). Just make sure that your adapter properly handles having an empty data set.