RecyclerView覆盖列表项

时间:2016-08-30 11:48:28

标签: android android-recyclerview picasso retrofit2 openweathermap

我正在开发一个任务管理器应用程序。基本上使用google places api我选择将其保存到sqlite数据库的位置并将其填入RecyclerView。对于每个位置,我使用retrofit2openweather api获取该位置的当前天气并将其显示在RecyclerView中。这是在位于onBindViewHolder方法的recyclerview适配器中的异步任务中完成的。现在,当我创建一个任务时,它将数据获取到该位置没有任何问题。当我添加更多任务时,问题就开始了。基本上,当我使用新位置添加新任务时,它会覆盖最后添加的任务的当前天气,如下图所示。

https://s9.postimg.org/l6tmi3wm7/Screenshot_20160830_143608.png

我怎样才能使它不会覆盖以前的任务?

public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.ViewHolder> {

    private List<Task> taskList;

    private final String API_KEY = "8617b30a6fc114ad2ad929c111b76edf";
    private final String UNITS = "metric";
    private double latitude, longitude;
    private Task task;
    private WeatherInfo weatherInfo;
    private Context context;

    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView taskName, destination, currentWeather;

        private ImageView weatherImg;

        public ViewHolder(View view) {
            super(view);
            taskName = (TextView) view.findViewById(R.id.task);
            destination = (TextView) view.findViewById(R.id.date);
            currentWeather = (TextView) view.findViewById(R.id.weather);
            weatherImg = (ImageView) view.findViewById(R.id.weather_icon);
        }
    }

    public TaskAdapter(List<Task> taskList) {
        this.taskList = taskList;
    }

    public void add(int position, Task item) {
        taskList.add(position, item);
        notifyItemInserted(position);
    }

    public void remove(Task item) {
        int position = taskList.indexOf(item);
        taskList.remove(position);
        notifyItemRemoved(position);
    }

    public Task getTask(int position) {
        return taskList.get(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        context = parent.getContext();
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_rv, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        task = taskList.get(position);
        latitude = task.getDestinationLatitude();
        longitude = task.getDestinationLongitude();


        new getWeatherDataAsync(holder).execute();


        holder.taskName.setText(task.getTaskName());
        holder.destination.setText(task.getDestinationName());
    }

    @Override
    public int getItemCount() {
        return taskList.size();
    }

    private class getWeatherDataAsync extends AsyncTask<Void, Void, Void> {

        private ViewHolder holder;
        private ProgressDialog progressDialog;

        public getWeatherDataAsync(ViewHolder holder) {
            this.holder = holder;
        }

        @Override
        protected void onPreExecute() {
            progressDialog=ProgressDialog.show(context,"Loading...","Getting weather.");
        }

        @Override
        protected Void doInBackground(Void... vHolders) {
            try {

                WeatherApi weatherApi = WeatherApi.retrofit.create(WeatherApi.class);
                Call<WeatherInfo> call = weatherApi.getWeatherData(latitude, longitude, API_KEY, UNITS);
                weatherInfo = call.execute().body();

//
            } catch (IOException e) {
                Log.e("get weather coordinates", "something went wrong: " + e.getMessage());
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            if (weatherInfo != null) {
                holder.currentWeather.setText(String.valueOf(weatherInfo.getMain().getTemp()) + "\u2103");
                getWeatherIcon(holder);

            } else {
                holder.currentWeather.setText("N/A \u2103");
                Picasso.with(context).load("file:///android_asset/md-weather-iconset/weather-none-available.png").into(holder.weatherImg);
            }


            progressDialog.dismiss();

        }

    }

    /**
     * Display the correct weather icon from assets based on the data returned from the Retrofit query.
     * @param viewHolder
     */
    private void getWeatherIcon(ViewHolder viewHolder){
         String base="file:///android_asset/md-weather-iconset";



        switch (weatherInfo.getWeather().get(0).getIcon()) {
            case "01d":
                Picasso.with(context).load(base+"/weather-clear.png").into(viewHolder.weatherImg);
                break;
            case "02d":
                Picasso.with(context).load(base+"/weather-few-clouds.png").into(viewHolder.weatherImg);
                break;
            case "03d":
                Picasso.with(context).load(base+"/weather-clouds.png").into(viewHolder.weatherImg);
                break;
            case "04d":
                Picasso.with(context).load(base+"/weather-clouds.png").into(viewHolder.weatherImg);
                break;
            case "09d":
                Picasso.with(context).load(base+"/weather-showers-day.png").into(viewHolder.weatherImg);
                break;
            case "10d":
                Picasso.with(context).load(base+"/weather-rain-day.png").into(viewHolder.weatherImg);
                break;
            case "11d":
                Picasso.with(context).load(base+"/weather-storm-day.png").into(viewHolder.weatherImg);
                break;
            case "13d":
                Picasso.with(context).load(base+"/weather-snow.png").into(viewHolder.weatherImg);
                break;
            case "50d":
                Picasso.with(context).load(base+"/weather-mist.png").into(viewHolder.weatherImg);
                break;
            case "01n":
                Picasso.with(context).load(base+"/weather-clear-night.png").into(viewHolder.weatherImg);
                break;
            case "02n":
                Picasso.with(context).load(base+"/weather-few-clouds-night.png").into(viewHolder.weatherImg);
                break;
            case "03n":
                Picasso.with(context).load(base+"/weather-clouds-night.png").into(viewHolder.weatherImg);
                break;
            case "04n":
                Picasso.with(context).load(base+"/weather-clouds-night.png").into(viewHolder.weatherImg);
                break;
            case "09n":
                Picasso.with(context).load(base+"/weather-showers-night.png").into(viewHolder.weatherImg);
                break;
            case "10n":
                Picasso.with(context).load(base+"/weather-rain-night.png").into(viewHolder.weatherImg);
                break;
            case "11n":
                Picasso.with(context).load(base+"/weather-storm-night.png").into(viewHolder.weatherImg);
                break;
            case "13n":
                Picasso.with(context).load(base+"/weather-snow.png").into(viewHolder.weatherImg);
                break;
            case "50n":
                Picasso.with(context).load(base+"/weather-mist.png").into(viewHolder.weatherImg);
                break;


        }
    }


}

3 个答案:

答案 0 :(得分:0)

首先,您能否明确表示您的预期产出是多少?也许图像显示您的预期输出和您获得的输出就足够了。我还建议你不要从你的适配器中的网络中取出,而是获取片段中的所有weatherdata并将信息传递给适配器。让我们说你有一个Activity持有recyclerview。使用接口从适配器调用asynctask。

同时将纬度和经度存储在视图中,然后再次尝试查看它是否有效。

答案 1 :(得分:0)

您正在使用onBindViewHolder()启动异步任务并将引用传递给holder。不幸的是,这不是RecyclerView应该如何工作的。 RecyclerView使用ViewHolder模式重用已经实例化的不再可见的布局,这就是为什么持有者可能在网络响应开始时代表完全不同的项目。

你应该做的是,在其他地方移动调用异步调用(例如Fragment / Activity / Presenter),从回调更新你的taskList集合,并使用以下方法之一通知适配器数据集已更改:

notifyDataSetChanged()

notifyItemInserted()

看看RecyclerView.Adapter docs:

ReyclerView.Adapter

答案 2 :(得分:0)

问题是

private WeatherInfo weatherInfo;

在AsyncTask中创建WeatherInfo对象。这将解决您的问题。 执行AsyncTask并创建新的WeatherInfo对象。现在将该对象传递给方法。

像这样改变方法

getWeatherIcon(ViewHolder viewHolder,WeatherInfo  wetherInfo)

这将解决您的问题。