How set Jsoup data to RecyclerView in AsyncTask - android

I'm parsing website title from URL, and set this title to RecyclerView item. When I call constructor, but I must use AsyncTasck for correctly work Jsoup. How can I set received data to RecyclerView?
I can do public MyAsyncTasck instead of private, but i don't now if it is right.
My MainActivity.java:
public class MainActivity extends AppCompatActivity {
public static final String TAG = "mLog";
#BindView(R.id.recycler_view)
RecyclerView recyclerView;
#BindView(R.id.imageView)
ImageView imageView;
private RecyclerView.Adapter adapter;
private List<ListItem> listItems;
ListItem item;
String URL = "https://sinoptik.ua/%D0%BF%D0%BE%D0%B3%D0%BE%D0%B4%D0%B0-
%D0%B2%D0%B8%D0%BD%D0%BD%D0%B8%D1%86%D0%B0";
Document document;
// Received data from Jsoup
String head = "something";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
listItems = new ArrayList<>();
item = new ListItem(head, "desc1");
listItems.add(item);
adapter = new MyRecViewAdapter(listItems, this);
recyclerView.setAdapter(adapter);
}
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
try {
document = Jsoup.connect(URL).get();
head = document.title();
} catch (IOException e ) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
// ??????
}
}
}
And MyRecViewAdapter.java:
public class MyRecViewAdapter extends RecyclerView.Adapter<MyRecViewAdapter.ViewHolder>{
private List<ListItem> listItems;
private Context context;
public MyRecViewAdapter(List<ListItem> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
//return our view
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ListItem listItem = listItems.get(position);
holder.tvHead.setText(listItem.getHead());
holder.tvDesc.setText(listItem.getDesc());
}
#Override
public int getItemCount() {
return listItems.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvHead;
public TextView tvDesc;
public ViewHolder(View itemView) {
super(itemView);
tvHead = (TextView) itemView.findViewById(R.id.tv_head);
tvDesc = (TextView) itemView.findViewById(R.id.tv_desc);
}
}
}
And the ListItem.java
public class ListItem {
private String head;
private String desc;
public ListItem(String head, String desc) {
this.head = head;
this.desc = desc;
}
public String getHead() {
return head;
}
public String getDesc() {
return desc;
}
}

You need to set the data got from your API call using the AsyncTask into your listItems which are being represented in your RecyclerView. Then you need to call notifyDataSetChanged in order to show the newly updated the in your RecyclerView.
So you need to modify the doInBackground function in your AsyncTask like the following.
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
try {
document = Jsoup.connect(URL).get();
listItems.clear();
ListItem item = new ListItem(document.title, document.desc);
listItems.add(item);
adapter.notifyDataSetChanged();
} catch (IOException e ) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
// ??????
}
}

Related

How to update an item on a recyclerview after excuting AsyncTask doInBackground?

I'm creating a chat feature for an application and it works super fine. But I would like to show the user that message has been sent or it still wating for the server's response.
Fields:
List<ChatMessage> chatMessages;
ChatAdapter chatAdapter;
RecyclerView chatRecyclerView;
ImageButton submitMessageBtn;
this how I send a message on my ChatActivity class:
public void submitMessage(final String messageType, final byte[] message){
final ChatMessageResponse messageObject = new ChatMessageResponse();
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
messageObject.setMessage( message);
messageObject.setYours(true);
messageObject.setUserNickname(getNickname());
messageObject.setCreationDate(DateTime.now().withZone(DateTimeZone.UTC));
messageObject.setType(messageType);
AddMessage(messageObject);
}
#Override
protected Void doInBackground(Void... voids) {
try {
chatClient.chat().sendMessage(eventId, messageType, message);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Update message on the list after has been sent to server
}
});
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
public void AddMessage(ChatMessage message)
{
chatMessages.add(message);
chatAdapter.notifyDataSetChanged();
chatRecyclerView.scrollToPosition(chatMessages.size() -1);
}
When message is immediatly added to the adapter it should look like this:
my ChatAdapter class is setup like this:
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {
private static final int VIEW_TYPE_MESSAGE_THIS_USER = 0;
private static final int VIEW_TYPE_MESSAGE_OTHER_USER = 1;
private final Activity activity;
public List<ChatMessage> chats=new ArrayList<>();
ArrayList<String> usercolor=new ArrayList<>();
Context mContext;
View view;
public ChatAdapter(List<ChatMessage> chats, Context mContext, Activity activity) {
this.chats = chats;
this.mContext = mContext;
this.activity = activity;
}
#Override
public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
mContext = parent.getContext();
if (viewType == VIEW_TYPE_MESSAGE_OTHER_USER) {
view = View.inflate(mContext, R.layout.message_item_left, null);
} else if (viewType == VIEW_TYPE_MESSAGE_THIS_USER){
view = View.inflate(mContext, R.layout.message_item, null);
}
return new ChatViewHolder(view,(View.OnLongClickListener)activity);
}
#Override
public void onBindViewHolder(final ChatViewHolder holder, int position){
final ChatMessageResponse m = (ChatMessageResponse) chats.get(position);
if (getItemViewType(position) == VIEW_TYPE_MESSAGE_OTHER_USER){
holder.bindToView1(m);
} else if (getItemViewType(position) == VIEW_TYPE_MESSAGE_THIS_USER)
{
holder.bindToView(m);
}
}
#Override
public int getItemCount() {
return chats.size();
}
#Override
public int getItemViewType(int position) {
return chats.get(position).isYours() ? VIEW_TYPE_MESSAGE_THIS_USER : VIEW_TYPE_MESSAGE_OTHER_USER;
}
}
When the server's response is positive the views in the ChatViewHolder (that I don't show the code because is too long) should change visibility state
Someone told me to get a referece for the view and change it on the activity's asynctask or create a Callback listener for my adapter.
But I have no Idea how to do either one of then any help is appreciated.
Are you familiar with the use of "Callbacks" or "Interfaces"? You can create an interface and implement it in your activity. Pass the callback by parameters in the "AsyncTask" and use it there.
//Interface class
/**
* Created by gmora
*/
public interface IProcess {
void updateAdapter(String result);
}
On Activity:
public class YourActivity extends AppCompatActivity {
private IProcess mProcess;
private Adapter mRecyclerAdapter;
private RecyclerView mRecyclerView;
private List<ChatMessage> chats; //update chats on activity and refresh your adapter
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mProcess = new IProceso() {
#Override
public void updateAdapter(String pException) {
//update chats ... and update mAdater.notifyDataChange()...
// or mRecyclerView.setAdapter(new Adpater.... with new list chats)..
}
};
mRecyclerView = find....
// etc....
mRecyclerAdapter = new RecyclerAdapter( chats, ...);
mRecyclerView.setAdapter(mRecyclerAdapter);
}
}
Finally on AsyncTask... create a external class from AsyncTask please!
/**
* Created by gmora.
*/
public class YourAsyncTaskClass extends AsyncTask<String, Void, String > {
private IProcess iProcess;
public StarSearchPrinterTask(IProcess pIProcess) {
this.iProcess= pIProcess;
}
#Override
protected void onPreExecute() {
//loading... its optional
}
#Override
protected String doInBackground(String... interfaceType) {
// execute webservice or api and get results..
return results;
}
#Override
protected void onPostExecute(String results) {
mIProceso.updateAdapter(results);
}
}

How to intent a parse query?

In parse i have a class A which has a column (relation) named - view, which relates to class B( contains different images with different object id's).Now what i want to achieve is that : in android i have a activity(A) which has a recycle view which shows all the items of class A. The items are clickable which when clicked brings up the items from class B in parse to activity(B) . Now the issue is we are unable to intent a parse query from activity (A) to activity(B), so that we can display the items of class B in Activity(B).
Is there any different method for this? Any example for this would be of additional help.
EDIT
MainActivity
public class MainActivity extends AppCompatActivity {
ProgressDialog mProgressDialog;
GridAdapter gridAdapter;
RecyclerView recyclerView;
private List<Grid_G_S> grid_list = new ArrayList<>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the view from gridview_main.xml
setContentView(R.layout.activity_main);
// Execute RemoteDataTask AsyncTask
new RemoteDataTask().execute();
}
// RemoteDataTask AsyncTask
private class RemoteDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressdialog
mProgressDialog = new ProgressDialog(MainActivity.this);
// Set progressdialog title
mProgressDialog.setTitle("Parse.com GridView Tutorial");
// Set progressdialog message
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// Create the array
grid_list = new ArrayList<>();
try {
ParseQuery<ParseObject> query = new ParseQuery<>("CardViewClass");
List<ParseObject> object1 = query.find();
for (final ParseObject country : object1) {
// Locate images in flag column
ParseFile image = (ParseFile) country.get("images");
ParseRelation<ParseObject> p = country.getRelation("view");
ParseQuery p2 = p.getQuery();
String f = image.getUrl();
Log.i("yji"," "+p2);
List<ParseObject> oc = p2.find();
for (ParseObject country2:oc){
ParseFile imgs = (ParseFile) country2.get("autoImage");
String fr = imgs.getUrl();
}
Grid_G_S setter = new Grid_G_S();
setter.setX(p2);
setter.setTitles((String) country.get("scrollText1"));
setter.setImages(f);
grid_list.add(setter);
}
}catch (ParseException e){
Log.e("err", e.getMessage());
} catch (com.parse.ParseException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
recyclerView = (RecyclerView) findViewById(R.id.recycler);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(),3);
gridAdapter = new GridAdapter(MainActivity.this, grid_list);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(gridAdapter);
mProgressDialog.dismiss();
}
GridAdapter
public class GridAdapter extends RecyclerView.Adapter {
Context context;
LayoutInflater inflater;
private List<Grid_G_S> grid_g_sList = null;
private ArrayList<Grid_G_S> arraylist;
public GridAdapter(Context context, List<Grid_G_S> grid_list) {
this.context = context;
this.grid_g_sList = grid_list;
inflater = LayoutInflater.from(context);
this.arraylist = new ArrayList<>();
this.arraylist.addAll(grid_list);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView titles;
ImageView gridImages;
View mview;
MyViewHolder(View v) {
super(v);
mview = v;
titles = (TextView) v.findViewById(R.id.grid_single_text);
gridImages = (ImageView) v.findViewById(R.id.grid_single_image);
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.grid_single_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
Grid_G_S item = grid_g_sList.get(position);
holder.titles.setText(item.getTitles());
Picasso.with(context)
.load(grid_g_sList.get(position).getImages())
.into(holder.gridImages);
holder.mview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, Secondactivity.class);
intent.putExtra("image", grid_g_sList.get(position).getImages());
intent.putExtra("query", String.valueOf(grid_g_sList.get(position).getX()));
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return grid_g_sList.size();
}
GridGetterSetter
public class Grid_G_S {
String Images;
String Titles;
ParseQuery x;
public String getImages() {
return Images;
}
public void setImages(String images) {this.Images = images;}
public String getTitles() {
return Titles;
}
public void setTitles(String titles) {this.Titles = titles;}
public ParseQuery getX() {
return x;
}
public void setX(ParseQuery x) {this.x = x;}
SecondActivity
public class Secondactivity extends AppCompatActivity {
String q1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_secondactivity);
new DownloadingTask().execute();
Intent i = getIntent();
String images = i.getStringExtra("image");
q1 = i.getStringExtra("query");
Log.i("this is ", " " + q1);
}
private class DownloadingTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
ParseQuery<ParseObject> query = new ParseQuery<>("CardViewClass");
try {
List<ParseObject> object1 = query.find();
for (final ParseObject country : object1) {
// Locate images in flag column
}
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}

Passing ArrayList from AsyncTask to PagerAdapter

hope you fine and well,
i have the following main class :
public class MainActivity extends AppCompatActivity {
Activity activity;
ViewPager viewPager;
CustomAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager=(ViewPager)findViewById(R.id.view_pager);
adapter=new CustomAdapter(this);
viewPager.setAdapter(adapter);
ConnectionAsyncTask connectionAsyncTask = new
ConnectionAsyncTask(MainActivity.this);
connectionAsyncTask.execute("http://www.mocky.io/v2/570d3677270000f600dc29b6");
}
public void showUploader()
{
// findViewById(R.id.progressBar1).setVisibility(View.VISIBLE);
}
public void hideUploader()
{
//findViewById(R.id.progressBar1).setVisibility(View.GONE);
}
public void DisplyOnTextView(List< Student > students) {
List <Student> my = students ;
}
}
when i run the app, this main activity will use another class to read json data from link as follows:
public class StudentJasonParser {
public static List<Student> getObjectFromJason(String jason)
{
List<Student> students;
try {
JSONArray jsonArray = new JSONArray(jason);
students = new ArrayList<>();
for(int i=0;i<jsonArray.length();i++)
{
JSONObject jsonObject = new JSONObject();
jsonObject= (JSONObject) jsonArray.get(i);
Student student = new Student();
student.setID(jsonObject.getInt("id"));
student.setName(jsonObject.getString("name"));
student.setUrl(jsonObject.getString("url"));
student.setDes(jsonObject.getString("des\n"));
student.setRate(jsonObject.getDouble("rate"));
student.setLon(jsonObject.getDouble("lon"));
student.setLat(jsonObject.getDouble("lat"));
students.add(student);
}
} catch (JSONException e) {
e.printStackTrace();
return null;
}
return students;
}
}
now this class will return the data to the following class :
public class ConnectionAsyncTask extends AsyncTask<String,String,String> {
Activity activity;
public ConnectionAsyncTask(Activity activity) {
this.activity=activity;
}
#Override
protected void onPreExecute() {
//((MainActivity)activity).DisplyOnTextView();
((MainActivity)activity).showUploader();
}
#Override
protected String doInBackground(String... params) {
String content =HttpManager.getData(params[0]);
return content;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String s) {
((MainActivity)activity).hideUploader();
List<Student> students= StudentJasonParser.getObjectFromJason(s);
if (students != null) {
((MainActivity) activity).DisplyOnTextView(students);
}
}
}
this line : ((MainActivity)activity).DisplyOnTextView(students);
will return the fetched data to the main class in the following function (mentioned in the main class ! )
public void DisplyOnTextView(List< Student > students) {
List <Student> my = students ;
}
now what i want is to pass this list to the following class in order to use it in the imageView and textView in the viewPager instead of the pre-defined data in the class :
public class CustomAdapter extends PagerAdapter {
private int[] images = {R.drawable.sample_0,R.drawable.sample_1};
private Context ctx;
private LayoutInflater LayoutInflater;
public CustomAdapter(Context ctx)
{
this.ctx=ctx;
}
#Override
public int getCount() {
return images.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view==(LinearLayout)object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = LayoutInflater.inflate(R.layout.slide_layout,container,false);
ImageView imageView =(ImageView) view.findViewById(R.id.image_view);
TextView textView = (TextView)view.findViewById(R.id.image_count);
imageView.setImageResource(images[position]);
textView.setText(""+position);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout) object);
}
}
any idea ?!
thanks, regards.
what i want is to pass this list to the following class in order to use it in the imageView and textView in the viewPager
Then simply pass in the list as a parameter to the adapter and add a member variable for it. The usage of this adapter is at the bottom of this post, because I want to mention some other stuff.
class CustomAdapter extends PagerAdapter {
private Context ctx;
private List<Student> data;
public CustomAdapter(Context ctx, List<Student> students) {
this.ctx = ctx;
this.data = students;
}
If you want to use that data variable in the instantiateItem method, then you can do Student s = this.data.get(position); and use the various methods on the Student object to load the TextView or ImageView.
Please note that you will need an image loading library (Picasso, Glide, Fresco, etc.) to load a URL into an ImageView. While on the topic of libraries, though, you will save yourself much development time by looking into Gson for JSON parsing and Retrofit or Volley for HTTP network calls with JSON data.
As for your usage of the AsyncTask, passing around the Activity variable is bad practice. Try to use an asynchronous callback to the Activity instead.
public interface AsyncResponse<T> {
void onResponse(T response);
}
public class ConnectionAsyncTask extends AsyncTask<String, Void, List<Student>> {
private AsyncResponse<List<Student>> callback;
public ConnectionAsyncTask(AsyncResponse<List<Student>> callback) {
this.callback = callback;
}
#Override
protected List<User> doInBackground(String... params) {
String url = params[0];
final List<Student> students = new ArrayList<Student>();
// TODO: JSON stuff
return students;
}
#Override
protected void onPostExecute(List<Student> result) {
if (this.callback != null) {
this.callback.onResponse(result);
} else {
Log.w("ConnectionAsyncTask", "Ignoring result");
}
}
}
public class SampleViewPagerActivity extends Activity {
private ViewPager pager;
private PagerAdapter adapter;
private ArrayList<Student> students;
private ProgressDialog progress;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1. Inflate a layout
setContentView(R.layout.viewpager_activity);
// 2. Initialize the views
this.pager = (ViewPager) findViewById(R.id.pager);
this.progress = new ProgressDialog(this);
this.progress.setTitle("Loading");
this.progress.setMessage("Please wait");
// 3. Populate the views with data
this.students = new ArrayList<Student>();
this.adapter = new CustomAdapter(this, students);
this.pager.setAdapter(adapter);
// This code runs later, after 'execute' is called and the response is returned
ConnectionAsyncTask task = new ConnectionAsyncTask(new AsyncResponse<List<Student>>() {
#Override
public void onResponse(List<Student> response) {
students.clear();
students.addAll(response);
adapter.notifyDataSetChanged();
progress.hide();
}
});
// Optionally show some progress while waiting
this.progress.show();
// TODO: Use real URL
task.execute("http://www.somesite.com/data");
}
}

Display Image from clicked item of Recyclerview

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();

My Listview Returns nothing while using retrofit

I am new to retrofit,i am just trying to json parsing, i don't know what i missed?
The list view is not displaying. Kindly help me with issue.I am using ListAcivity with List Adapter.This is Strange to me .Please help with this.
This is Client.java
public class UtubeClient {
private static UtubeApiInterface UtubeService;
public static UtubeApiInterface getTwitchTvApiClient() {
if (UtubeService== null) {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://tamilpasanga.in")
.build();
UtubeService = restAdapter.create(UtubeApiInterface.class);
}
return UtubeService;
}
public interface UtubeApiInterface {
#GET("/mytuts/list.json")
void getStreams( Callback<List<UtubeChannel>> callback);
}
}
Get the callback in mainActvity
MainActivity.java
public class MainActivity extends ListActivity {
//private ProgressBar mProgressBar;
private List<UtubeChannel> streamData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
streamData = new ArrayList<UtubeChannel>();
// mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
setListAdapter(new MobileArrayAdapter(this,streamData));
downloadDatainRetrofit();
}
private void downloadDatainRetrofit() {
// mProgressBar.setVisibility(View.VISIBLE);
UtubeClient.getTwitchTvApiClient().getStreams(new Callback<List<UtubeChannel>>() {
#Override
public void success(List<UtubeChannel> utubeChannels, Response response) {
streamData.addAll(utubeChannels) ;
}
#Override
public void failure(RetrofitError retrofitError) {
//
}
}
);
}
}
UTubeChannel.java
public class UtubeChannel {
private String url;
private String name;
UtubeChannel(String url,String name){
this.url=url;
this.name=name;
}
public String getUrl()
{
return this.url;
}
public void setUrl(String url)
{
this.url=url;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name= name;
}
}
Mobile Array Adapter
public class MobileArrayAdapter extends ArrayAdapter<UtubeChannel> {
protected static final String TAG = null;
private final Context context;
String outFileName;
private LayoutInflater inflater;
public MobileArrayAdapter(final Context context, List<UtubeChannel > objects) {
super(context, R.layout.listview_item, objects);
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context = context;
}
#Override
public View getView(int position, View rowView, ViewGroup parent) {
ViewHolder holder = null;
if (rowView == null) {
rowView = inflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.name = (TextView) rowView.findViewById(R.id.name);
holder.url = (TextView) rowView.findViewById(R.id.url);
// viewHolder.button.setTag(viewHolder.text);
// viewHolder.text.setTag(viewHolder.button);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
UtubeChannel channel= getItem(position);
holder.name.setText(channel.getName());
holder.url.setText(channel.getUrl());
return rowView;
}
static class ViewHolder {
public TextView url;
public TextView name;
}
}
you passed empty list to your adapter, then you have tried download data from Internet but as you don't call, notifyDatasetChanged your list not showing anything. so you need change your code too :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
streamData = new ArrayList<UtubeChannel>();
// mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
downloadDatainRetrofit();
}
private void downloadDatainRetrofit() {
// mProgressBar.setVisibility(View.VISIBLE);
UtubeClient.getTwitchTvApiClient().getStreams(new Callback<List<UtubeChannel>>() {
#Override
public void success(List<UtubeChannel> utubeChannels, Response response) {
streamData.addAll(utubeChannels) ;
setListAdapter(new MobileArrayAdapter(this,streamData));
}
#Override
public void failure(RetrofitError retrofitError) {
//
}
});
}
or you can use:
1 - create one global value in your class as:
MobileArrayAdapter adapter.
2- in onCreate use:
adapter = new MobileArrayAdapter(this,streamData);
setListAdapter(adapter);
3- after downloading data use:
adapter.notifyDatasetChanged();
for refreshing list data

Categories

Resources