Android回收站视图未正确显示输出

时间:2016-03-25 12:27:56

标签: android android-recyclerview

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

第一个困惑是:为什么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();

}

Async类编写为:

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()。如果我在notifyDataSetChanged()doInBackground()方法中使用postExecute,它只会指向Null指针异常,所以这就是我在适配器中使用它的原因,但我认为它是好吧也可以在那里使用它。

请帮助你们!

2 个答案:

答案 0 :(得分:1)

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

1)异步任务,因其名称suggets执行其任务异步。也就是说,行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,以通知适配器有关更改。

答案 1 :(得分:0)

尝试使用 Picasso Glide 库下载图像。这些库可能提供更快的下载,其缓存处理更好。