显示来自 Recyclerview 单击项目的图像
Display Image from clicked item of Recyclerview
我正在尝试从已经填充的 recyclerview 中获取图像字符串,以便我可以在另一个 activity 的图像视图中显示该图像。在这里,我使用 jsoup 获取图像的路径(url):
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));
}
到 elements
变量,然后将其存储到 arraylist 中。我想获取图像(存储在 elements
中)的路径(url),以便我可以在另一个 activity 中显示该图像。我尝试使用以下方法从 arrayList
中检索 url:
public String getImageUrl(int pos)
{
return arrayList.get(pos).getThumb();
}
但是抛出IndexOutOfBound
异常,说index(pos)无效,arrayList
的size为0,不知道为什么说list有size 0,而 Recyclerview 得到 pouplated 并显示我使用 jsoup
解析的数据。请帮帮我,我被困了三天。
好的,完整的代码在这里:
这是显示 recyclerview
的主要 activity
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);
}
}
}
这些是适配器、viewholder 和数据 类:
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);
}
}
取景器:
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);
}
}
数据:
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;
}
}
罪魁祸首是:
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child));
您实际上是在创建一个新的 AsyncTask
- 如果您尝试从新的 AsyncTask
中的 arrayList
获取一个元素,很明显列表是空的,因为任务填充doInBackground()
方法中的列表,它还没有被执行。
解法:
在您的 onCreate 方法中,创建您的 getDataAsyncTask
并在成员变量中保留对它的引用。
然后,当任务完成执行并调用 onPostExecute(Void aVoid)
时,设置一个标志来指示该事实。
接下来,在您的 onClickListener
中,引用 相同的 任务,但仅当 asyncTaskFinished 标志设置为 true 时才执行代码:
public class RestaurantsAndCafesActivity 扩展 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;
}
}
在异步任务中:
@Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
adapter = new RCRecyclerAdapter(getApplicationContext(),arrayList);
mRecyclerView.setAdapter(adapter);
asyncTaskFinished = true;
}
请注意,这是一种对现有代码进行最小更改的解决方案,但我建议采用不同的方法 - 将列表保留在 AsyncTask 中有点难看,更好的方法是从 doInBackground return ,并在 onPostExecute 中,将其传递给适配器(同时不在任务中保留对它的 class-scope 引用),当您需要访问列表中的元素时,只需引用适配器,而不是您的 AsyncTask:
imgUrl = adapter.getList().get(recyclerView.getChildPosition(child)).getThumb();
我正在尝试从已经填充的 recyclerview 中获取图像字符串,以便我可以在另一个 activity 的图像视图中显示该图像。在这里,我使用 jsoup 获取图像的路径(url):
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));
}
到 elements
变量,然后将其存储到 arraylist 中。我想获取图像(存储在 elements
中)的路径(url),以便我可以在另一个 activity 中显示该图像。我尝试使用以下方法从 arrayList
中检索 url:
public String getImageUrl(int pos)
{
return arrayList.get(pos).getThumb();
}
但是抛出IndexOutOfBound
异常,说index(pos)无效,arrayList
的size为0,不知道为什么说list有size 0,而 Recyclerview 得到 pouplated 并显示我使用 jsoup
解析的数据。请帮帮我,我被困了三天。
好的,完整的代码在这里: 这是显示 recyclerview
的主要 activitypublic 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);
}
}
}
这些是适配器、viewholder 和数据 类:
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);
}
}
取景器:
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);
}
}
数据:
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;
}
}
罪魁祸首是:
imgUrl = new getDataAsyncTask().getImageUrl(recyclerView.getChildPosition(child));
您实际上是在创建一个新的 AsyncTask
- 如果您尝试从新的 AsyncTask
中的 arrayList
获取一个元素,很明显列表是空的,因为任务填充doInBackground()
方法中的列表,它还没有被执行。
解法:
在您的 onCreate 方法中,创建您的 getDataAsyncTask
并在成员变量中保留对它的引用。
然后,当任务完成执行并调用 onPostExecute(Void aVoid)
时,设置一个标志来指示该事实。
接下来,在您的 onClickListener
中,引用 相同的 任务,但仅当 asyncTaskFinished 标志设置为 true 时才执行代码:
public class RestaurantsAndCafesActivity 扩展 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;
}
}
在异步任务中:
@Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
adapter = new RCRecyclerAdapter(getApplicationContext(),arrayList);
mRecyclerView.setAdapter(adapter);
asyncTaskFinished = true;
}
请注意,这是一种对现有代码进行最小更改的解决方案,但我建议采用不同的方法 - 将列表保留在 AsyncTask 中有点难看,更好的方法是从 doInBackground return ,并在 onPostExecute 中,将其传递给适配器(同时不在任务中保留对它的 class-scope 引用),当您需要访问列表中的元素时,只需引用适配器,而不是您的 AsyncTask:
imgUrl = adapter.getList().get(recyclerView.getChildPosition(child)).getThumb();