2

我正在開發一個任務管理器應用程序。基本上與谷歌地方的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; 


     } 
    } 


} 
+0

嘗試'holder.currentWeather.setText(task.getTemperatur());' – Abbas

回答

0

您正在使用onBindViewHolder()啓動異步任務並將holder的引用傳遞給它。不幸的是,這不是RecyclerView應該如何工作。 RecyclerView使用ViewHolder模式重用已經實例化的不再可見的佈局,這就是爲什麼當網絡響應啓動時持有者可能代表完全不同的項目。

你應該做的是將異步調用移動到其他地方(例如片段/活動/演示),從回調更新taskList集合,並通知該數據集已使用下列方法之一更改適配器:

notifyDataSetChanged()

notifyItemInserted()

看看錄像yclerView.Adapter文檔:

ReyclerView.Adapter

+0

歡呼你指出我正確的方向。 –

+0

不客氣,祝你有美好的一天 – pawelo

0

首先您能清楚地知道您的預期輸出是什麼。也許一張圖片顯示你的預期輸出和你得到的輸出就足夠了。我還建議你不要從適配器內部的網絡中獲取數據,而是獲取片段中的所有天氣數據,並將信息傳遞給適配器。讓我們說你有一個持有recyclerview的Activity。使用接口從適配器調用asynctask。

還存儲經緯度在viewholder中,並再次嘗試,看看它是否工作。

0

問題是

private WeatherInfo weatherInfo; 

創建內部的AsyncTask WeatherInfo對象。這將解決您的問題。 AsyncTask被執行,它將創建新的WeatherInfo對象。現在將該對象傳遞給方法。

這樣

getWeatherIcon(ViewHolder viewHolder,WeatherInfo wetherInfo) 

這種變化方法解決您的問題。