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();
Related
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) {
// ??????
}
}
I've get some Json data from server by okhttp ,and I want to show them in a
recycleview inside of a fragment using a custom adapter and receiving the following error.
when I run this code,the logcat tell me the followeing msg:
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
I print the list in the logcat ,it shows null.
but I can get some json data from the IE.Do anyone help me,please?
public class customer extends AppCompatActivity {
private static final String TAG = "MyDebug______ " ;
private RecyclerView cutomerRecyclerView;
private customerAdapter mAdapter;
private ArrayList<custModal> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer);
Toolbar toolbar = (Toolbar)findViewById(R.id.custom_toolbar);
setSupportActionBar(toolbar);
new getHttpData().execute();
Log.d(TAG, "the list is :" +list);
mAdapter = new customerAdapter(this,list);
cutomerRecyclerView = (RecyclerView)findViewById(R.id.customer_list);
cutomerRecyclerView.setLayoutManager(new LinearLayoutManager(this));
cutomerRecyclerView.setAdapter(mAdapter);
cutomerRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration(){
#Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state){
super.onDraw(c,parent,state);
c.drawColor(R.color.colorDevider);
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.offset(0,1);
}
});
}
public class customerAdapter extends RecyclerView.Adapter<customerAdapter.customerViewHolder>{
private Context mcontext;
private ArrayList<custModal> mlist;
// private LayoutInflater inflater;
class customerViewHolder extends RecyclerView.ViewHolder{
private TextView name,mem,cust_id;
public customerViewHolder(View view){
super(view);
cust_id = (TextView )view.findViewById(R.id.cust_id);
name = (TextView)view.findViewById(R.id.cust_name);
mem = (TextView)view.findViewById(R.id.cust_mem);
}
}
public customerAdapter(Context context,ArrayList<custModal> list){
this.mcontext = context;
this.mlist = list;
}
#Override
public customerViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
customerViewHolder holder = new customerViewHolder(LayoutInflater.from(
customer.this).inflate(R.layout.customer_item,parent,false));
return holder;
}
#Override
public void onBindViewHolder(customerViewHolder holder,int position){
holder.cust_id.setText(mlist.get(position).getId());
holder.name.setText(mlist.get(position).getName());
holder.mem.setText(mlist.get(position).getMobiphone());
}
#Override
public int getItemCount(){ return mlist.size();}
}
class custModal {
private String id;
private String name;
private String gender;
private String mobiphone;
private String creat_time;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getGender() {
return gender;
}
public void setMobiphone(String mobiphone) {
this.mobiphone = mobiphone;
}
public String getMobiphone() {
return mobiphone;
}
public void setCreat_time(String creat_time) {
this.creat_time = creat_time;
}
public String getCreat_time() {
return creat_time;
}
}
public class getHttpData extends AsyncTask<String,Integer,ArrayList<custModal> >{
//private ArrayList<custModal> custlist;
#Override
// protected void onPreExecute(){}
#Override
protected ArrayList<custModal> doInBackground(String... params){
String url = "http://aaaa.bbbbb.cn/index.php/mobi/customer/app_getlist";
try{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
String responseData = response.body().string();
Log.d(TAG, "doInBackground: "+ responseData);
if(responseData != null){
//return getCustFromJson(responseData);
Gson gson = new Gson();
ArrayList<custModal> custlist = gson.fromJson(responseData,
new TypeToken<List<custModal>>() {}.getType()
);
return custlist;
}else{
return null;
}
}catch (IOException I){
I.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ArrayList<custModal> custlist){
if(!custlist.isEmpty()){
super.onPostExecute(custlist);
list = custlist;
mAdapter.notifyDataSetChanged();
}
}
}
}
make sure initialize adapter, array list of adapter and attaching adapter to recycler in onCreate
You have to then add the new yourAsyncTask().execute where you need to to http call.
In your onBackground add items to the array list and in postExecute simply call notify data change method
Your list is in a null state when you pass it via adapter constructor therefore any operations on the list return null.
You could add a callback to your okhttp request and construct the adapter on the response? One way or another though you need to update the list before you can perform any operations on it.
I put the following code into the Method onPostExecute,it worked.But I think it is not a right solution.like this:
protected void onPostExecute(ArrayList<custModal> custlist){
Log.d(TAG, "onPostExecute(Result result) called");
Log.d(TAG, "onPostExecute: "+custlist);
mAdapter = new customerAdapter(customer.this,custlist);
cutomerRecyclerView = (RecyclerView)findViewById(R.id.customer_list);
cutomerRecyclerView.setLayoutManager(new LinearLayoutManager(customer.this));
cutomerRecyclerView.setAdapter(mAdapter);
}
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");
}
}
I have a adapter with this code:
public class LoadOrders_adapter extends BaseAdapter {
private JSONArray data;
private Context context;
public LoadOrders_adapter(JSONArray data, Context context) {
this.data = data;
this.context = context;
}
#Override
public int getCount() {
return data.length();
}
#Override
public Object getItem(int position) {
try {
return data.get(position);
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.loading_orderlist, parent, false);
ImageView product_images=(ImageView) row.findViewById(R.id.product_images);
TextView Total_quantity = (TextView) row.findViewById(R.id.Total_quantity);
TextView order_status=(TextView) row.findViewById(R.id.order_status);
TextView order_date = (TextView) row.findViewById(R.id.order_date);
TextView order_id = (TextView) row.findViewById(R.id.order_id);
TextView product_Name=(TextView) row.findViewById(R.id.product_Name);
try {
JSONObject temp = data.getJSONObject(position);
Picasso.with(context).load(WebConnection.getInstance().resource_url(temp.getString("imgUrl"))).into(product_images);
Total_quantity.setText(temp.getString("Quantity"));
order_date.setText(temp.getString("Date_Sub"));
order_id.setText("#"+temp.getString("Order_ID"));
order_status.setText(temp.getString("Status"));
product_Name.setText(temp.getString("Name"));
} catch (JSONException e) {
e.printStackTrace();
}
return row;
}
}
And a class called:
public class LoadOrders extends ActionBarActivity implements Top_fragment.Top_fragmentListener {
private JSONArray data = null;
private JSONArray OrderDetails2 = null;
private ListView Normal_Orders_list;
private String previous_activity = "info.sliit.mystyle.Home";
private String title_name = "Your Normal Orders";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_promotional_wear);
Normal_Orders_list = (ListView)findViewById(R.id.Normal_Orders_list);
new BackgroundProcess().execute();
}
class BackgroundProcess extends AsyncTask<Void,Void,Void> {
ProgressDialog progressDialog = new ProgressDialog(LoadOrders.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Loading data...");
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
data = WebConnection.getInstance().get_request("Loading_order_rest/orderloading/user_id/12","json");
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
BaseAdapter baseAdapter1 = new LoadOrders_adapter(data,LoadOrders.this);
Normal_Orders_list.setAdapter(baseAdapter1);
//Normal_Orders_list.setOnItemClickListener();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_customized_orders,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public String get_previous_activity() {
return previous_activity;
}
#Override
public String getTitle_name() {
return title_name;
}
}
I have an activity called Activity_loading_orders which has a list view called Normal_Orders_list and i have another layout called loading_orderlist which has has a RelativeLayout with some Textviews and a button. As you can see in the code the layout loading_orderlist is loaded as an list item into the Normal_Orders_list activity. What i want to do is to remove list items when the button is clicked see image http://i.imgur.com/TYAqd0t.jpg
My Jason taken from postman
<?xml version="1.0" encoding="utf-8"?>
<xml><data><datum><Order_ID>8</Order_ID><Quantity>52</Quantity><Comment>fs</Comment><Date_Sub>2015-08-27</Date_Sub><Date_Del/><Product_ID/><Customer_ID>12</Customer_ID><Status>Accepted</Status><View>Unread</View><Name>T-shirt</Name><imgUrl>\assets\images\projectpics\normalt\Edited_front.jpg</imgUrl></datum><datum><Order_ID>10</Order_ID><Quantity>45</Quantity><Comment>sf</Comment><Date_Sub>2015-08-27</Date_Sub><Date_Del/><Product_ID/><Customer_ID>12</Customer_ID><Status>Accepted</Status><View>Unread</View><Name>T-shirt</Name><imgUrl>\assets\images\projectpics\normalt\Edited_front.jpg</imgUrl></datum></data></xml>
Consider moving the JSON parsing outside of getView(). What you're going to want to do is:
Have a (preferably) List of <ParsedJsonObject> (from parsing the JSON) instead of a JsonArray
On 'cancel' click: delete item at position from the List
After deleting the item from the list, notify your adapter that it's dataset has changed: mListViewAdapter.notifyDataSetChanged();
Please note: I'm afraid you're going to have to change to a custom ArrayAdapter instead of a BaseAdapter. The reason for this is that you are using a JSONArray as the data set for the adapter. It's not a good idea to start messing with the JSON yourself, but you're going to have to remove the item from the dataset one way or another. I recommend you take a look at libraries such as gson or Genson.
Those libraries can deserialize JSON into Java objects for you. So what'd you'd end up doing:
Fetch JSON data
Deserialize JSON data into Java objects, put these objects into a List<ParsedJsonObject>
Create a new ArrayAdapter<ParsedJsonObject>
Pass along the list of ParsedJsonObjects as the dataset for the ArrayAdapter you just created.
getView() won't have to change a lot, just change where the data comes from. getView() lets you know what position you are in, and considering you passed along a List<ParsedJsonObject>, you can just do list.get(position) to return an object containing all the data.
I hope this helped!
All right, so here's what you need to do:
Create new classes: DataModel.java, Data.java, and Datum.java
Put this in them:
DataModel.java:
public class DataModel {
private Data data;
public Data getData ()
{
return data;
}
public void setData (Data data)
{
this.data = data;
}
}
Data.java:
public class Data {
private Datum[] datum;
public Datum[] getDatum ()
{
return datum;
}
public void setDatum (Datum[] datum)
{
this.datum = datum;
}
}
Datum.java:
public class Datum{
private String Name;
private String View;
private String Status;
private String Quantity;
private String Date_Sub;
private String Comment;
private String Customer_ID;
private String Order_ID;
private String imgUrl;
public String getName ()
{
return Name;
}
public void setName (String Name)
{
this.Name = Name;
}
public String getView ()
{
return View;
}
public void setView (String View)
{
this.View = View;
}
public String getStatus ()
{
return Status;
}
public void setStatus (String Status)
{
this.Status = Status;
}
public String getQuantity ()
{
return Quantity;
}
public void setQuantity (String Quantity)
{
this.Quantity = Quantity;
}
public String getDate_Sub ()
{
return Date_Sub;
}
public void setDate_Sub (String Date_Sub)
{
this.Date_Sub = Date_Sub;
}
public String getComment ()
{
return Comment;
}
public void setComment (String Comment)
{
this.Comment = Comment;
}
public String getCustomer_ID ()
{
return Customer_ID;
}
public void setCustomer_ID (String Customer_ID)
{
this.Customer_ID = Customer_ID;
}
public String getOrder_ID ()
{
return Order_ID;
}
public void setOrder_ID (String Order_ID)
{
this.Order_ID = Order_ID;
}
public String getImgUrl ()
{
return imgUrl ;
}
public void setImgUrl (String imgUrl)
{
this.imgUrl = imgUrl;
}
}
And then in your class do Data d = genson.deserialize(jsonString, DataModel.class);
Inside DataModel is a Data instance and inside that is your array of datum's
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.