请我尝试在我的recyclerview中发布JSON数据。我正在使用AsyncTaskLoader,但屏幕上没有显示任何内容。 我已经从JSON记录了我需要的数据,以确认我得到了正确的解析,然后它们出现了。我还记录了要显示的对象数组,它们也显示在logcat中,它只是我的应用程序的屏幕,不显示任何数据。我正在使用带有2个片段的视图寻呼机,这两个问题都是一样的。 这是我的FragmentActivity,由于问题是相同的,我将只发布一个
public class TechNewsFragment extends Fragment {
private SwipeRefreshLayout mSwipeRefreshLayout;
private TextView mErrorMessage;
private NewsAdapter mNewsAdapter;
ArrayList<News> news;
NetworkInfo info;
// The Loader takes in a bundle
Bundle sourceBundle = new Bundle();
private final String LOG_TAG = MainActivity.class.getSimpleName();
private static final String TECH_NEWS_QUERY_URL = "query";
private static final String TECH_NEWS_SOURCE = "techcrunch";
private static final int TECH_NEWS_LOADER = 22;
private RecyclerView mRecyclerView;
public TechNewsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_news, container, false);
mErrorMessage = (TextView) view.findViewById(R.id.tv_error_message);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_main);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefresh);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
getActivity().getSupportLoaderManager().initLoader(TECH_NEWS_LOADER, null, new NewsDataLoader());
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Log.v(LOG_TAG, "Refreshing");
restartLoader();
mSwipeRefreshLayout.setColorSchemeResources(
R.color.colorPrimary,
R.color.colorPrimaryDark);
}
});
return view;
}
private boolean isConnected(){
ConnectivityManager cm = (ConnectivityManager) getActivity()
.getSystemService(CONNECTIVITY_SERVICE);
info = cm.getActiveNetworkInfo();
return info != null && info.isConnectedOrConnecting();
}
private int anyRandomInt(Random random) {
return random.nextInt();
}
private void restartLoader() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
URL techNewsUrl = TechNetworkUtils.buildUrl(TECH_NEWS_SOURCE);
sourceBundle.putString(TECH_NEWS_QUERY_URL, techNewsUrl.toString());
Random random = new Random();
int uniqueId = anyRandomInt(random); //Generates a new ID for each loader call;
// sourceBundle.putString("query", s);]
LoaderManager loaderManager = getActivity().getSupportLoaderManager();
if (loaderManager.getLoader(TECH_NEWS_LOADER) == null) {
loaderManager.initLoader(uniqueId, sourceBundle, new NewsDataLoader());
} else {
loaderManager.restartLoader(TECH_NEWS_LOADER, sourceBundle, new
NewsDataLoader());
}
}
}, 5000);
mSwipeRefreshLayout.setRefreshing(false);
Log.v(LOG_TAG, "Finished refreshing");
}
private void showErrorScreen(){
mErrorMessage.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.INVISIBLE);
mErrorMessage.setText(getString(R.string.internet_error));
}
`public class NewsDataLoader implements LoaderManager.LoaderCallbacks<ArrayList<News>> {
@Override
public Loader<ArrayList<News>> onCreateLoader(int id, final Bundle args) {
if (isConnected()){
mErrorMessage.setVisibility(View.INVISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
return new AsyncTaskLoader<ArrayList<News>>(getActivity()) {
ArrayList<News> mNewsData;
@Override
protected void onStartLoading() {
super.onStartLoading();
if (mNewsData != null){
deliverResult(mNewsData);
}else{
forceLoad();
mSwipeRefreshLayout.setRefreshing(true);
}
}
@Override
public ArrayList<News> loadInBackground() {
try {
ArrayList<News> news = TechNetworkUtils.parseJSON(TECH_NEWS_SOURCE);
return news;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public void deliverResult(ArrayList<News> data) {
mNewsData = data;
super.deliverResult(data);
}
};
}else{
showErrorScreen();
return null;
}
}
@Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
mSwipeRefreshLayout.setRefreshing(false);
if (null == data) {
showErrorScreen();
} else {
mErrorMessage.setVisibility(View.INVISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
if (news != null) {
// news.clear();
news.addAll(data);
mNewsAdapter = new NewsAdapter(news);
mRecyclerView.setAdapter(mNewsAdapter);
mNewsAdapter.notifyDataSetChanged();
} else {
news = data;
}
Log.i(LOG_TAG + " this is the data", data.toString());
// Array of objects shows in the log
}
}
@Override
public void onLoaderReset(Loader<ArrayList<News>> loader) {
// loader.forceLoad();
}
}
}`
这是我的适配器类
public class NewsAdapter extends
RecyclerView.Adapter<NewsAdapter.NewsHolder> {
// Variable used to reference the model
private ArrayList<News> mNews = new ArrayList<>();
// NewsHolder class that extends the ViewHolder
public static class NewsHolder extends RecyclerView.ViewHolder{
private TextView mNewsTextView;
private TextView mTimeStampTextView;
// Constructor to set the views
public NewsHolder(View itemView){
super(itemView);
mNewsTextView = (TextView) itemView.findViewById(R.id.news_tv);
mTimeStampTextView = (TextView) itemView.findViewById(R.id.time_tv);
}
}
// Constructor to set the adapter
public NewsAdapter(ArrayList<News> news){
mNews = news;
}
@Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =
LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_view,
parent, false);
return new NewsHolder(view);
}
@Override
public void onBindViewHolder(NewsHolder holder, int position) {
holder.mNewsTextView.setText(mNews.get(position).getNews());
holder.mTimeStampTextView.setText(mNews.get(position).getTime());
}
@Override
public int getItemCount() {
return mNews.size();
}
}`
这是解析JSON并处理网络连接的类
public class TechNetworkUtils {
private static final String LOG_TAG = MainActivity.class.getSimpleName();
public static ArrayList<News> parseJSON(String source) throws IOException {
URL url = buildUrl(source);
String jsonResult = getResponseFromHttpUrl(url);
ArrayList<News> news = new ArrayList<>();
try{
JSONObject jsonObject = new JSONObject(jsonResult);
JSONArray jsonArray = jsonObject.getJSONArray("articles");
if (jsonArray != null){
for (int i = 0; i < jsonArray.length(); i++){
JSONObject article = jsonArray.getJSONObject(i);
String title = article.getString("title");
String time = article.getString("publishedAt");
news.add(new News(title, time));
Log.i(LOG_TAG, title);
Log.i(LOG_TAG, time);
}
}
}catch (JSONException | NullPointerException e){
e.printStackTrace();
return null;
}
return news;
}
public static URL buildUrl(String techNewsSource){
final String TECH_NEWS_BASE_URL = "https://newsapi.org/v1/articles";
final String PARAM_SOURCE = "source";
final String PARAM_SORT_BY = "sortBy";
final String latest = "latest";
final String PARAM_API_KEY = "apiKey";
final String KEY = "3431d57e51a04c1d967e2eb96c99fd1a";
Uri builtUri = Uri.parse(TECH_NEWS_BASE_URL).buildUpon()
.appendQueryParameter(PARAM_SOURCE, techNewsSource)
.appendQueryParameter(PARAM_SORT_BY, latest)
.appendQueryParameter(PARAM_API_KEY, KEY)
.build();
Log.i(LOG_TAG, builtUri.toString());
URL url = null;
try{
url = new URL(builtUri.toString());
}catch (MalformedURLException e){
e.printStackTrace();
}
return url;
}
public static String getResponseFromHttpUrl(URL url) throws IOException{
HttpURLConnection urlConnection = null;
String newsJsonStr = null;
BufferedReader reader = null;
try{
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(15000);
urlConnection.setConnectTimeout(10000);
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(false);
urlConnection.setDoInput(true);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if(inputStream == null){
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null){
buffer.append(line + "\n");
}
if (buffer.length() == 0){
return null;
}
newsJsonStr = buffer.toString();
}catch(IOException e){
Log.e(LOG_TAG, "Error fetching data", e);
return null;
}finally{
if (urlConnection != null){
urlConnection.disconnect();
}
if (reader != null){
try{
reader.close();
}catch (IOException e){
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return newsJsonStr;
}
}
这是我的pojo课程
public class News {
private String mNews;
private String mTime;
public News(String news, String time){
mNews = news;
mTime = time;
}
public String getNews() {
return mNews;
}
public String getTime() {
return mTime;
}
}`
这是我的list_item_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/title_frame">
<TextView
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="64dp"
android:id="@+id/news_tv"
tools:text="Get exciting news here"/>
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end">
<TextView
android:id="@+id/time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingRight="16dp"
tools:text="12:00pm"/>
</FrameLayout>
</LinearLayout>
这是我的log.i
/* 06-06 21:35:25.834 1092-1092/com.ire.blogbot E/dalvikvm: Could not
find
class 'android.graphics.drawable.RippleDrawable', referenced from method
android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
06-06 21:35:25.834 1092-1092/com.ire.blogbot W/dalvikvm: VFY: unable to
resolve instanceof 146 (Landroid/graphics/drawable/RippleDrawable;) in
Landroid/support/v7/widget/AppCompatImageHelper;
06-06 21:35:25.922 1092-1106/com.ire.blogbot I/MainActivity:
https://newsapi.org/v1/articles?source=entertainment-
weekly&sortBy=top&apiKey=3431d57e51a04c1d967e2eb96c99fd1a
06-06 21:35:25.934 1092-1107/com.ire.blogbot I/MainActivity:
https://newsapi.org/v1/articles?
source=techcrunch&sortBy=latest&apiKey=3431d57e51a04c1d967e2eb96c99fd1a
06-06 21:35:26.042 1092-1092/com.ire.blogbot W/EGL_genymotion:
eglSurfaceAttrib not implemented
06-06 21:35:26.226 376-423/system_process I/ActivityManager: Displayed
com.ire.blogbot/.activity.MainActivity: +606ms
06-06 21:35:26.270 376-449/system_process I/qtaguid: Failed write_ctrl(s 0
10021) res=-1 errno=1
06-06 21:35:26.270 376-449/system_process W/NetworkManagementSocketTagger:
setKernelCountSet(10021, 0) failed with errno -1
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: How can tech
companies treat their contractors better?
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T21:19:28Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: Audi is the
first to test autonomous vehicles in New York
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T20:58:34Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: Bragi’s Dash
Pro is a sophisticated and smart AirPods alternative
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T20:05:41Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: As the Surface
line courts creatives, Apple pushes back with the iMac and iPad Pro
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T20:04:19Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: What Silicon
Valley can learn from Lebanon’s women in tech
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T20:00:53Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: Matt Mitchell
of CryptoHarlem is building an open source tool to help organizations
prepare for data breaches
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T19:29:04Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: Pinterest
raises $150M at a $12.3B valuation as it makes a full press into
visual search
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T19:27:05Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: Tulip, the app
platform for manufacturers, picks up $13 million from NEA
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T18:45:34Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: Take a look at
these first pictures of Fisker’s $130K EMotion electric car
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T18:27:57Z
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: iOS 11 will
help you free up storage on your iPhone through personalized suggestions
06-06 21:35:27.182 1092-1107/com.ire.blogbot I/MainActivity: 2017-06-
06T18:22:33Z
06-06 21:35:27.182 1092-1092/com.ire.blogbot
I/MainActivity this is the data: [com.ire.blogbot.model.News@536e8250,
com.ire.blogbot.model.News@536e65c0, com.ire.blogbot.model.News@536d157c,
com.ire.blogbot.model.News@536e80ec, com.ire.blogbot.model.News@536e80f8,
com.ire.blogbot.model.News@536e8104, com.ire.blogbot.model.News@536e8110,
com.ire.blogbot.model.News@536e811c, com.ire.blogbot.model.News@536e8128,
com.ire.blogbot.model.News@536e8134]
06-06 21:35:27.202 1092-1106/com.ire.blogbot I/MainActivity:
{"status":"ok","source":"entertainment-weekly","sortBy":"top","articles":
[{"author":null,"title":"The Zodiac Killer: How a first-time filmmaker
attempted to catch the serial
murderer","description":null,"url":"http://zodiactruecrime.ew.com/","urlT
oImage":null,"publishedAt":null},{"author":"Maureen Lee Lenker","title":"Sam
Smith teases return to the recording studio with
new photos","description":"","url":"http://ew.com/music/2017/06/06/sam-
smith-teases-new-
album/","urlToImage":"http://i0.wp.com/ewedit.files.wordpress.com/2017/06/g
ettyimages-521740878.jpg?
crop=0px%2C82px%2C2700px%2C1418px&resize=1200%2C630&ssl=1","publishedAt":"2
017-06-06T21:22:08Z"},{"author":"Marisa Marcellino","title":"Highest-
grossing
Broadway shows of
all time","description":"","url":"http://ew.com/theater/2017/06/06/highest-
grossing-broadway-shows-of-all-
time/","urlToImage":"http://i1.wp.com/ewedit.files.wordpress.com/2017/03/li
onking.jpg?
crop=0px%2C42px%2C2700px%2C1419px&resize=1200%2C630&ssl=1","publishedAt":"2
017-06-06T19:52:02Z"},{"author":"Kyle Fowle","title":"'House of Cards'
Recap:
How Far Is Claire Willing to Go to Secure the
Presidency?","description":"With threats forming all around them, Frank and
Claire take violent action to secure their
legacy","url":"http://ew.com/recap/house-of-cards-season-5-episode-
12/","urlToImage":"http://i0.wp.com/ewedit.files.wordpress.com/2017/06/hoc_
512_unit_01846r.jpg?
crop=3px%2C105px%2C2699px%2C1418px&resize=1200%2C630&ssl=1","publishedAt":"
2017-06-06T19:49:12Z"},{"author":"Nivea Serrao","title":"Selena Gomez
responds
to ’13 Reasons Why’ controversy","description":"'This is happening every
day'","url":"http://ew.com/tv/2017/06/06/selena-gomez-13-reasons-why-
controversy-
2/","urlToImage":"http://i1.wp.com/ewedit.files.wordpress.com/2017/04/13rw_
113_01153r.jpg?
crop=0px%2C53px%2C2700px%2C1418px&resize=1200%2C630&ssl=1","publishedAt":"2
017-06-06T19:45:59Z"},{"author":"Ruth Kinane","title":"‘Hollywood Game
Night’
teaser: ‘This Is Us,’ ‘Veep,’ ‘Walking Dead’ casts ready
for battle","description":"Jane Lynch returns to
host","url":"http://ew.com/tv/2017/06/06/hollywood-game-night-teaser-this-
is-us-veep-walking-dead-
casts/","urlToImage":"http://i1.wp.com/ewedit.files.wordpress.com/2017/06/h
ollywoodgame.jpg?
crop=0px%2C21px%2C2700px%2C1419px&resize=1200%2C630&ssl=1","publishedAt":"2
017-06-06T19:30:49Z"},{"author":"Joey Nolfi","title":"Watch Jerry Seinfeld
refuse a hug from Kesha","description":"\"I don't know who that was... I
wish her the best,\" the 63-year-old
said","url":"http://ew.com/news/2017/06/06/jerry-seinfeld-kesha-
hug/","urlToImage":"http://i0.wp.com/ewedit.files.wordpress.com/2017/06/sei
nfeldkesha.jpg?
crop=0px%2C13px%2C3200px%2C1681px&resize=1200%2C630&ssl=1","publishedAt":"2
017-06-06T19:05:57Z"},{"author":"Maureen Lee Lenker","title":"Tonys 2017:
Watch
performances from this year’s Best
Musical nominees","description":"","url":"http://ew.com/theater/2017/06/06/
tonys-2017-nominations-best-musical-
performances/","urlToImage":"http://i2.wp.com/ewedit.files.wordpress.com/20
17/0
6/deh-ben-platt-4449-photo.jpg?
crop=0px%2C382px%2C2700px%2C1419px&resize=1200%2C630&ssl=1","publishedAt":"
2017
-06-06T19:00:59Z"},{"author":"Ray Rahman","title":"‘Broad City’ returns
under a ‘cloud of doom,’ stars tease","description":"Plus: RuPaul makes a
'f---ing titillating' and 'godlike'
cameo","url":"http://ew.com/tv/2017/06/06/broad-city-season-4-
winter/","urlToImage":"http://i2.wp.com/ewedit.files.wordpress.com/2017/06/
broadcity.jpg?
crop=0px%2C87px%2C2700px%2C1419px&resize=1200%2C630&ssl=1","publishedAt":"2
017-06-06T18:56:12Z"},{"author":"Nivea Serrao","title":"How ‘The Moth’
podcast
turned storytelling into a
worldwide movement","description":"","url":"http://ew.com/podcasts/2017/06/
06/the-moth-podcast-20th-
anniversary/","urlToImage":"http://i1.wp.com/ewedit.files.wordpress.com/201
7/06/gettyimages-530299778.jpg?
crop=0px%2C18px%2C1800px%2C945px&resize=1200%2C630","publishedAt":"2017-
06-06T18:48:15Z"}]}
06-06 21:35:33.406 376-386/system_process I/ActivityManager: No longer want
com.android.exchange (pid 870): hidden #16
06-06 21:41:36.890 55-55/? W/Genyd: Can't parse request
06-06 21:41:36.958 376-466/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:36.958 376-466/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:36.958 376-389/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:36.958 376-389/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:36.958 376-389/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:37.158 376-466/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:37.158 376-466/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:37.162 376-389/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:37.162 376-389/system_process I/ClipboardService: Got clipboard
for user=0
06-06 21:41:37.162 376-389/system_process I/ClipboardService: Got clipboard
for user=0
我需要在启动应用程序时自动显示数据,并在调用onSwipeRefreshLayout时刷新。
答案 0 :(得分:0)
我已经运行了你的项目而我没有收到你从logcat发布的错误,而是我在这行代码中得到了NullPointerException
:
String techNewsUrlString = args.getString(TECH_NEWS_QUERY_URL);
所以我将args
替换为您的sourceBundle
并修复了错误:
String techNewsUrlString = sourceBundle.getString(TECH_NEWS_QUERY_URL);
第二个问题出在您的fragment_news
xml代码中。您的TextView
占用了所有空间而Recyclerview
没有空间,所以我做了一些更改:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv_error_message"
android:text="Oops! Couldn't connect to a network"
android:gravity="center"
android:layout_margin="32dp"
android:textSize="16sp"
android:fontFamily="monospace"
android:visibility="invisible"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
您的项目现在应该可以使用。