Android回收站视图未正确显示输出(Android recycler view not showing the output properly)

编程入门 行业动态 更新时间:2024-10-25 01:29:12
Android回收站视图未正确显示输出(Android recycler view not showing the output properly)

首先,请帮助......我已经做了几乎所有的事情,现在我在这里!

第一个困惑是:为什么Async类工作得那么慢,我使用click事件从api获取一些数据,同时使用SYSO查看Android监视器中填充数组的输出,每次几乎需要4.5秒用20个元素填充arraylist。 必须有一些我现在不知道的错误......

活动代码是:

Toolbar toolbar; RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_news); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // Get Request String url = "MY URL HERE"; new JSONAsync(getApplicationContext()).execute(url); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(MainNews.this, JSONAsync.dataArray); recyclerViewAdapter.notifyDataSetChanged(); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recyclerViewAdapter); recyclerViewAdapter.notifyDataSetChanged(); }

异步类编写为:

Context context; public static List<Data> dataArray = new ArrayList<>(); public JSONAsync(Context context) { this.context = context; dataArray.clear(); } @Override protected Boolean doInBackground(String... params) { try { return downloadUrl(params[0]); } catch (IOException e) { return false; } catch (JSONException e) { e.printStackTrace(); } return null; } public boolean downloadUrl(String myurl) throws IOException, JSONException { InputStream is = null; int response; try { URL url = new URL(myurl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); response = conn.getResponseCode(); is = conn.getInputStream(); if (response == 200) { String responseBody = convertToString(conn.getInputStream()); JSONArray jArray = new JSONArray(responseBody); for (int i = 0; i < jArray.length(); i++) { JSONObject jobj = jArray.getJSONObject(i); System.out.println("Output is: ....."+jobj); Data data = new Data(); data.setId(jobj.getInt("id")); data.setHeading(jobj.getString("heading")); data.setBrief(jobj.getString("brief")); data.setDate(jobj.getString("date")); String imageURL = "http://paktribune.com/images/news/"; imageURL = imageURL.concat(jobj.getString("limage")); data.setImage(getBitmapFromURL(imageURL)); dataArray.add(data); } return true; } else return false; } finally { if (is != null) { is.close(); } } } public Bitmap getBitmapFromURL(String imageURL) { Bitmap myBitmap = null; try { int responseCode; URL url = new URL(imageURL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); responseCode = connection.getResponseCode(); if (responseCode==200) { InputStream input = connection.getInputStream(); myBitmap = BitmapFactory.decodeStream(input); } } catch (IOException e) { e.printStackTrace(); return null; } return myBitmap; } public String convertToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } catch (IOException e) { } finally { try { is.close(); } catch (IOException e) { } } return sb.toString(); } @Override protected void onPostExecute(Boolean result) { if (result == false) { Toast.makeText(context, "Unable to fetch data from server", Toast.LENGTH_SHORT).show(); } }

适配器是:

private LayoutInflater inflater; Context context; List<Data> dataArray; private int lastPosition = -1; public RecyclerViewAdapter(Context context, List<Data> dataArray) { this.dataArray = dataArray; this.context = context; inflater = LayoutInflater.from(context); } @Override public RecyclerViewAdapter.CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.cardview, parent, false); CustomViewHolder holder = new CustomViewHolder(view); return holder; } @Override public void onBindViewHolder(CustomViewHolder holder, int position) { Data current = dataArray.get(position); holder.textView1.setText(current.heading); holder.textView2.setText(current.date); holder.textView3.setText(current.brief); holder.image.setImageBitmap(current.image); setAnimation(holder.relativeLayout, position); } @Override public int getItemCount() { return dataArray.size(); } public static class CustomViewHolder extends admin.myproject.CustomViewHolder { ImageView image; RelativeLayout relativeLayout; TextView textView1, textView2, textView3; public CustomViewHolder(View itemView) { super(itemView); textView1 = (TextView) itemView.findViewById(R.id.heading); textView2 = (TextView) itemView.findViewById(R.id.date); textView3 = (TextView) itemView.findViewById(R.id.brief); image = (ImageView) itemView.findViewById(R.id.imageView); relativeLayout = (RelativeLayout) itemView.findViewById(R.id.Relative); } } private void setAnimation(View viewToAnimate, int position) { if (position > lastPosition) { Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left); viewToAnimate.startAnimation(animation); lastPosition = position; } }

任何人都可以告诉我为什么当我在doInBackground的循环完成之前单击某个按钮时应用程序移动到下一个活动。 我正在清除dataArray并更新notifyDataSetChanged() 。 如果我在doInBackground()或postExecute方法中使用notifyDataSetChanged() ,它只是指向Null指针异常,所以这就是我在适配器中使用它的原因,但我认为也可以在那里使用它。

请帮助伙计!

First of all, PLEASE HELP ... I have done almost everything to figure out and now I am here !

1st confusion is: why on earth Async class works so slow, I am using the click event to fetch some data from api, while using SYSO to see the output of populated array in Android monitor, it nearly took 4,5 seconds every time to populate the arraylist with 20 elements. There must be something very wrong which i dont know right now ....

Activity code is :

Toolbar toolbar; RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_news); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // Get Request String url = "MY URL HERE"; new JSONAsync(getApplicationContext()).execute(url); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(MainNews.this, JSONAsync.dataArray); recyclerViewAdapter.notifyDataSetChanged(); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recyclerViewAdapter); recyclerViewAdapter.notifyDataSetChanged(); }

Async class is written as:

Context context; public static List<Data> dataArray = new ArrayList<>(); public JSONAsync(Context context) { this.context = context; dataArray.clear(); } @Override protected Boolean doInBackground(String... params) { try { return downloadUrl(params[0]); } catch (IOException e) { return false; } catch (JSONException e) { e.printStackTrace(); } return null; } public boolean downloadUrl(String myurl) throws IOException, JSONException { InputStream is = null; int response; try { URL url = new URL(myurl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); response = conn.getResponseCode(); is = conn.getInputStream(); if (response == 200) { String responseBody = convertToString(conn.getInputStream()); JSONArray jArray = new JSONArray(responseBody); for (int i = 0; i < jArray.length(); i++) { JSONObject jobj = jArray.getJSONObject(i); System.out.println("Output is: ....."+jobj); Data data = new Data(); data.setId(jobj.getInt("id")); data.setHeading(jobj.getString("heading")); data.setBrief(jobj.getString("brief")); data.setDate(jobj.getString("date")); String imageURL = "http://paktribune.com/images/news/"; imageURL = imageURL.concat(jobj.getString("limage")); data.setImage(getBitmapFromURL(imageURL)); dataArray.add(data); } return true; } else return false; } finally { if (is != null) { is.close(); } } } public Bitmap getBitmapFromURL(String imageURL) { Bitmap myBitmap = null; try { int responseCode; URL url = new URL(imageURL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); responseCode = connection.getResponseCode(); if (responseCode==200) { InputStream input = connection.getInputStream(); myBitmap = BitmapFactory.decodeStream(input); } } catch (IOException e) { e.printStackTrace(); return null; } return myBitmap; } public String convertToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } catch (IOException e) { } finally { try { is.close(); } catch (IOException e) { } } return sb.toString(); } @Override protected void onPostExecute(Boolean result) { if (result == false) { Toast.makeText(context, "Unable to fetch data from server", Toast.LENGTH_SHORT).show(); } }

And the adapter is :

private LayoutInflater inflater; Context context; List<Data> dataArray; private int lastPosition = -1; public RecyclerViewAdapter(Context context, List<Data> dataArray) { this.dataArray = dataArray; this.context = context; inflater = LayoutInflater.from(context); } @Override public RecyclerViewAdapter.CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.cardview, parent, false); CustomViewHolder holder = new CustomViewHolder(view); return holder; } @Override public void onBindViewHolder(CustomViewHolder holder, int position) { Data current = dataArray.get(position); holder.textView1.setText(current.heading); holder.textView2.setText(current.date); holder.textView3.setText(current.brief); holder.image.setImageBitmap(current.image); setAnimation(holder.relativeLayout, position); } @Override public int getItemCount() { return dataArray.size(); } public static class CustomViewHolder extends admin.myproject.CustomViewHolder { ImageView image; RelativeLayout relativeLayout; TextView textView1, textView2, textView3; public CustomViewHolder(View itemView) { super(itemView); textView1 = (TextView) itemView.findViewById(R.id.heading); textView2 = (TextView) itemView.findViewById(R.id.date); textView3 = (TextView) itemView.findViewById(R.id.brief); image = (ImageView) itemView.findViewById(R.id.imageView); relativeLayout = (RelativeLayout) itemView.findViewById(R.id.Relative); } } private void setAnimation(View viewToAnimate, int position) { if (position > lastPosition) { Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left); viewToAnimate.startAnimation(animation); lastPosition = position; } }

Can anyone tell me why the app moves to the next activity when i click some button before the loop in doInBackground completes. I am clearing the dataArray and also updating the notifyDataSetChanged(). If i use the notifyDataSetChanged() in doInBackground() or in postExecute method, it just points the Null pointer exception so this is the reason I am using it in adapter but i think it's okay to use it there as well.

PLEASE HELP guys !

最满意答案

您的逻辑存在缺陷,实施容易受到许多问题的影响。

1)异步任务,因为其名称suggets 异步执行其任务。 也就是说, new JSONAsync(getApplicationContext()).execute(url);行new JSONAsync(getApplicationContext()).execute(url); 立即返回并在活动中继续执行。 当您告诉适配器数据已准备就绪时,它很可能还没有准备好,并且异步任务正在尝试同时完成其工作。

2)使用静态成员在多线程环境中进行通信容易出错。 相反,在您的活动中实现一个侦听器接口,让异步任务在onPostExecute调用侦听器的方法。 然后告诉适配器有关数据的更改。

private List<Data> dataArray = new ArrayList<>(); private IAsyncTaskListener listener; public JSONAsync(Context context, IAsyncTaskListener listener) { this.context = context; this.listener = listener; } public interface IAsyncTaskListener { void onCompleted(List<Data> dataArray); } @Override protected void onPostExecute(Boolean result) { this.listener.onCompleted(dataArray); }

您的活动可以实现IAsyncTaskListener

public class YourActivity extends AppCompatActivity implements JSONAsync.IAsyncTaskListener { @Override public void onCompleted(List<Data> dataArray) { recyclerViewAdapter.setData(dataArray); recyclerViewAdapter.notifyDataSetChanged(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_news); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // Get Request String url = "http://paktribune.com/api/newsList"; new JSONAsync(getApplicationContext(), this).execute(url); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(MainNews.this); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recyclerViewAdapter); } }

您将提供一种更改适配器数据的方法。 在侦听器回调中,您可以在适配器上设置数据并在其上调用notifyDataSetChanged ,以通知适配器有关更改的信息。

Your logic is flawed and the implementation is vulnerable to many problematic issues.

1) Async task, as its name suggets performs its task asynchronously. That is, the line new JSONAsync(getApplicationContext()).execute(url); returns immediately and execution continues in the activity. As you tell the adapter that data is ready, it most probably is not ready and async task is trying to do its job in the mean time.

2) Using the static member to communicate in a multi-threaded environment is prone to errors. Instead, implement a listener interface in your activity and let the async task call the listener's method in onPostExecute. Only then tell the adapter about the data change.

private List<Data> dataArray = new ArrayList<>(); private IAsyncTaskListener listener; public JSONAsync(Context context, IAsyncTaskListener listener) { this.context = context; this.listener = listener; } public interface IAsyncTaskListener { void onCompleted(List<Data> dataArray); } @Override protected void onPostExecute(Boolean result) { this.listener.onCompleted(dataArray); }

Your activity can implement IAsyncTaskListener

public class YourActivity extends AppCompatActivity implements JSONAsync.IAsyncTaskListener { @Override public void onCompleted(List<Data> dataArray) { recyclerViewAdapter.setData(dataArray); recyclerViewAdapter.notifyDataSetChanged(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_news); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // Get Request String url = "http://paktribune.com/api/newsList"; new JSONAsync(getApplicationContext(), this).execute(url); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(MainNews.this); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recyclerViewAdapter); } }

You would provide a method to change the adapter's data. In the listener callback, you set the data on the adapter and call notifyDataSetChanged on it, to inform the adapter about the changes.

更多推荐

本文发布于:2023-07-05 06:53:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1034359.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:回收站   视图   正确   Android   recycler

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!