【问题标题】:E/RecyclerView: No adapter attached; skipping layout using fragments and GSONE/RecyclerView:没有附加适配器;使用片段和 GSON 跳过布局
【发布时间】:2018-08-16 15:54:32
【问题描述】:

我试图寻找解决方案,但找不到适合我具体情况的解决方案。我正在使用recyclerviewGSON,我收到了跳过布局的消息。我的代码看起来正确,但我知道我应该在 onCreateView 部分设置一个空适配器。我不确定该怎么做。任何帮助将不胜感激。我的片段活动如下。

  @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_weather_app, container, false);

mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));

new GetWeatherAync().execute(getActivity());
return view;


 }
 private class GetWeatherAync extends AsyncTask<Context, Void,      
 List<ForecastWeatherList>> {
private String TAG = GetWeatherAync.class.getSimpleName();
private Context mContext;

@Override
protected void onPreExecute() {
    super.onPreExecute();
}

@Override
protected List<ForecastWeatherList> doInBackground(Context...params) {
    mContext = params[0];
    return getWeatherFromServer();
}

@Override
protected void onPostExecute(List<ForecastWeatherList> result) {
    super.onPostExecute(result);

    if (result != null) {
        Log.e(TAG, "populate UI recycler view with gson converted data");

        RecyclerViewAdapter weatherRecyclerViewAdapter = new RecyclerViewAdapter(result, mContext);
        mRecyclerView.setAdapter(weatherRecyclerViewAdapter);
    }

}
 }

 public List<ForecastWeatherList> getWeatherFromServer(){
String serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + searchView + api_key;
URL url = null;
try {
    url = new URL(serviceUrl);

    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    connection.setDoOutput(true);
    connection.setConnectTimeout(4000);
    connection.setReadTimeout(4000);
    connection.connect();

    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

    //pass buffered reader to convert json to javaobject using gson
    return convertJsonToObject(bufferedReader);

}catch (Exception e){

}

return null;
 }

 public List<ForecastWeatherList> convertJsonToObject(BufferedReader bufferedReader){
final Gson gson = new Gson();

//pass root element type to fromJson method along with input stream

ForecastWeatherListWrapper weatherWrapper = gson.fromJson(bufferedReader,ForecastWeatherListWrapper.class);

List<ForecastWeatherList> weatherlst = weatherWrapper.getforecastWeatherLists();

return weatherlst;
}

编辑:

所以我实施了以下更改:

监听器接口。

     import com.ksburneytwo.weathertest.ForecastWeather.ForecastWeatherList;

   import java.util.List;

   public interface Listener {
void afterSearch(List<ForecastWeatherList> result);
 }

片段:

   public static WeatherAppFragment newInstance(String param1, String param2) {
    WeatherAppFragment fragment = new WeatherAppFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_weather_app, container, false);

    mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));

    new GetWeatherAync().execute(getActivity());
    return view;
}





@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);
    SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);

    if (searchItem != null) {
        searchView = (SearchView) searchItem.getActionView();
    }
    if (searchView != null) {
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));

        queryTextListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                Log.i("onQueryTextChange", newText);

                return true;
            }

            @Override
            public boolean onQueryTextSubmit(String query) {
                Log.i("onQueryTextSubmit", query);

                return true;
            }
        };
        searchView.setOnQueryTextListener(queryTextListener);
    }
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public void afterSearch(List<ForecastWeatherList> result) {
    mRecyclerView.setAdapter(new RecyclerViewAdapter(result, mRecyclerView.getContext()));

}



private static class GetWeatherAync extends AsyncTask<Context, Void, List<ForecastWeatherList>> {
    private String TAG = GetWeatherAync.class.getSimpleName();
    private final String serviceUrl;
    private Context mContext;
    private Listener listener;

    GetWeatherAync(Listener listener,String searchView, String api_key) {
        this.listener = listener;
        this.serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + searchView + api_key;
    }

    @Override
    protected List<ForecastWeatherList> doInBackground(Context...params) {
        try {
            URL url = new URL(serviceUrl);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            connection.setConnectTimeout(4000);
            connection.setReadTimeout(4000);
            connection.connect();

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            ForecastWeatherListWrapper weatherWrapper = new Gson().fromJson(bufferedReader, ForecastWeatherListWrapper.class);
            return weatherWrapper.getforecastWeatherLists();
        } catch (Exception e) {}
        return null;
    }

    @Override
    protected void onPostExecute(List<ForecastWeatherList> result) {
        super.onPostExecute(result);
        if (result != null) {
            Log.e(TAG, "populate UI recycler view with gson converted data");
            listener.afterSearch(result);
        }
    }
}

这里是recyclerview 适配器。

 public class RecyclerViewAdapter  extends        
 RecyclerView.Adapter<RecyclerViewAdapter.ForecastRecycler> {

List<ForecastWeatherList> mForecastWeatherDataList;

public static class ForecastRecycler extends RecyclerView.ViewHolder{

public TextView currentTemp;
public TextView currentHumidity;
public TextView currentDescription;
public ImageView currentIcon;

public ForecastRecycler (View view) {
    super (view);

    currentTemp = (TextView) view.findViewById(R.id.current_temperature);
    currentHumidity = (TextView) view.findViewById(R.id.current_humidity);
    currentDescription = (TextView) view.findViewById(R.id.current_weather_description);
    currentIcon = (ImageView) view.findViewById(R.id.current_weather_icon);

}

}

public RecyclerViewAdapter(List<ForecastWeatherList> mForecastWeatherDataList, Context mContext) {
    this.mForecastWeatherDataList = mForecastWeatherDataList;
}

@Override
public ForecastRecycler onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);

        final ForecastRecycler  currentRecycler = new ForecastRecycler(view);

        return currentRecycler;
}

@Override
public void onBindViewHolder( ForecastRecycler holder, int position) {

    final ForecastWeatherList currentRecycler = mForecastWeatherDataList.get(position);
    holder.currentTemp.setText((currentRecycler.getMain().getTempKf()));
    holder.currentHumidity.setText(currentRecycler.getMain().getHumidity());
    holder.currentDescription.setText(currentRecycler.getWeather().getDescription());
    Picasso.with(holder.currentIcon.getContext()).load(currentRecycler.getWeather().getIcon());


}

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

}

这是我当前的日志。我知道它连接到服务器,但我仍然没有收到适配器连接错误。

11371-11371/com.ksburneytwo.weathertest D/debugMode:应用程序在 onCreateView 中

11371-11396/com.ksburneytwo.weathertest D/debugMode:应用程序在doInBackground中

11371-11371/com.ksburneytwo.weathertest E/RecyclerView:未连接适配器;跳过布局

11371-11396/com.ksburneytwo.weathertest D/NetworkSecurityConfig:未指定网络安全配置,使用平台默认值

11371-11396/com.ksburneytwo.weathertest D/debugMode: 应用程序在 catch 后停止

【问题讨论】:

  • 在 onCreateview() 中用一个空列表初始化你的适配器和 recyclerview,然后当你的异步任务加载你的数据列表时,只需将响应添加到列表中并通知适配器

标签: android json android-recyclerview gson


【解决方案1】:

在 onCreateView() 方法初始化后,在适配器中尝试notifyDataSetChanged()

或使用这种方法:

听众:

public interface Listener {
    void afterSearch(List<ForecastWeatherList> result);
}

片段:

 public class MyFragment extends Fragment implements Listener {
    RecyclerView mRecyclerView;
    List<ForecastWeatherList> items = new ArrayList<>();
    RecyclerViewAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_weather_app, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));

        adapter = new RecyclerViewAdapter(items, mRecyclerView.getContext());
        mRecyclerView.setAdapter(adapter);

        new GetWeatherAync(this, searchView, api_key).execute();
        return view;
    }

    public afterSearch(List<ForecastWeatherList> result) {
        items = result;
        adapter.notifyDataSetChanged();
    }
}

异步任务:

private static class GetWeatherAync extends AsyncTask<Context, Void, List<ForecastWeatherList>> {
    private String TAG = GetWeatherAync.class.getSimpleName();
    private final String serviceUrl;
    private Context mContext;
    private Listener listener;

    public GetWeatherAync(Listener listener, Object searchView, Object api_key) {
        this.listener = listener;
        this.serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + searchView + api_key;
    }

    @Override
    protected List<ForecastWeatherList> doInBackground(Context...params) {
        try {
            URL url = new URL(serviceUrl);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            connection.setConnectTimeout(4000);
            connection.setReadTimeout(4000);
            connection.connect();

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            ForecastWeatherListWrapper weatherWrapper = new Gson().fromJson(bufferedReader, ForecastWeatherListWrapper.class);
            return weatherWrapper.getforecastWeatherLists();
        } catch (Exception e) {}
        return null;
    }

    @Override
    protected void onPostExecute(List<ForecastWeatherList> result) {
       super.onPostExecute(result);
       if (result != null) {
           Log.e(TAG, "populate UI recycler view with gson converted data");
           listener.afterSearch(result);
       }
    }
}

【讨论】:

  • 我尝试使用第二种方法,但 android studio 无法识别监听器的实现(公共类 WeatherAppFragment 行为红色)和空的 GetWeatherAync()。括号有红色下划线。
  • 创建不同的类并将MyFragment更改为您的片段名称
  • 我进行了更改,但仍然收到有关 GetWeatherAync 的警告。 Studio 告诉我 GetWeatherAync 中的 GetWeatherAync() 不能应用于预期和实际参数。我已经用上面修改过的代码更新了我的问题。
  • 我的 logcat 中仍然出现跳过布局。我添加了我的 recyclerviewadapter,因为我认为这可能与它有关。
  • 我添加了一些标签,显然它在声明没有附加适配器之前到达 doInBackground。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 2020-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多