Recyclerview 在 activity 上正常工作,而 AsyncTask return 使用 Fragment 时为空值并崩溃
Recyclerview working correctly on activity while AsyncTask return null value when using Fragment and crash
以下所有代码都在 activity 上正常工作,但在尝试使用 Fragment 后,调试器显示它首先尝试调用 Fragment,然后尝试执行 AsyncTask class 不正确,它崩溃并且没有从 API 获得输入流值。我搜索了与我的问题相关的不同文章,但如果你愿意,我想在这里听取建议,这是我的代码如下:
activity_main.xml 文件代码行(其中包含片段将被添加或替换的容器):
<?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:id="@+id/mainactivity_container"
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"
android:orientation="vertical"
tools:context="com.example.prof_mohamedatef.tabletfragments.MainActivity">
</LinearLayout>
main_fragment.xml 文件代码行:
<?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="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/card_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity java 文件中的activity Container 与MainFragment 布局之间的beginTransaction 如下:
package com.example.prof_mohamedatef.tabletfragments;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainFragment mainFragment=new MainFragment();
getFragmentManager().beginTransaction()
.add(R.id.mainactivity_container,mainFragment)
.commit();
}
}
MainFragment java 文件正在 activity 上膨胀:
package com.example.prof_mohamedatef.tabletfragments;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
/**
* Created by Prof-Mohamed Atef on 9/8/2016.
*/
public class MainFragment extends android.app.Fragment{
private static final String TAG = "RecyclerViewFragment";
public MainFragment() {}
RecyclerView mRecyclerView;
public ImagesAdapter mAdapter;
ArrayList<MovieEntity> list = new ArrayList<MovieEntity>();
final String now = "http://api.themoviedb.org/3/movie/popular?api_key=868bebbf76a3831f11b3985c703cf959";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
update_START();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View rootView=inflater.inflate(R.layout.main_fragment,container,false);
rootView.setTag(TAG);
mRecyclerView = (RecyclerView)rootView.findViewById(R.id.card_recycler_view);
// mRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), 2);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
private void update_START() {
Fetch_Moview_data f_m_data = new Fetch_Moview_data();
f_m_data.execute(now);
}
public String main_List = "results";
public String POSTER_PATH = "poster_path";
public String VIDEO_ID = "id";
public String TITLE = "title";
public String OVERVIEW = "overview";
public String RELEASE_DATE = "release_date";
public String POPULARITY = "popularity";
public String VOTE_AVERAGE_="vote_average";
public String POSTER_PATH_STRING;
public String VIDEO_ID_STRING;
public String TITLE_STRING;
public String OVERVIEW_STRING;
public String RELEASE_DATE_STRING;
public String POPULARITY_STRING;
public String VOTE_AVERAGE_STRING;
public JSONObject MoviesJson;
public JSONArray moviesDataArray;
public JSONObject oneMovieData;
public class Fetch_Moview_data extends AsyncTask<String, Void, ArrayList<MovieEntity>> {
private final String LOG_TAG = Fetch_Moview_data.class.getSimpleName();
private ArrayList<MovieEntity> getMovieDataFromJson(String MoviesJsonStr)
throws JSONException {
MoviesJson = new JSONObject(MoviesJsonStr);
moviesDataArray = MoviesJson.getJSONArray(main_List);
list.clear();
for (int i = 0; i < moviesDataArray.length(); i++) {
// Get the JSON object representing a movie per each loop
oneMovieData = moviesDataArray.getJSONObject(i);
POSTER_PATH_STRING = oneMovieData.getString(POSTER_PATH);
VIDEO_ID_STRING = oneMovieData.getString(VIDEO_ID);
TITLE_STRING = oneMovieData.getString(TITLE);
OVERVIEW_STRING = oneMovieData.getString(OVERVIEW);
RELEASE_DATE_STRING = oneMovieData.getString(RELEASE_DATE);
POPULARITY_STRING = oneMovieData.getString(POPULARITY);
VOTE_AVERAGE_STRING=oneMovieData.getString(VOTE_AVERAGE_);
mAdapter=null;
MovieEntity entity = new MovieEntity(POSTER_PATH_STRING, VIDEO_ID_STRING, TITLE_STRING, OVERVIEW_STRING, RELEASE_DATE_STRING, POPULARITY_STRING,VOTE_AVERAGE_STRING);
list.add(entity);
}
return list;
}
@Override
protected ArrayList<MovieEntity> doInBackground(String... params) {
String Movies_images_JsonSTR = null;
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
if (params.length == 0) {
return null;
}
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
Movies_images_JsonSTR = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
Movies_images_JsonSTR = buffer.toString();
Log.v(LOG_TAG, "Movies JSON String: " + Movies_images_JsonSTR);
} catch (IOException e) {
Log.e(LOG_TAG, "Error here Exactly ", e);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}else {
Log.v(LOG_TAG, "Reader = null ( No Input Stream ) ");
}
}
try {
return getMovieDataFromJson(Movies_images_JsonSTR);
} catch (JSONException e) {
Log.e(LOG_TAG, "didn't got Movies Data from getJsonData method", e);
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ArrayList<MovieEntity> result) {
mAdapter=null;
list=result;
mAdapter = new ImagesAdapter(getContext(), result);
mRecyclerView.setAdapter(mAdapter);
}
}
}
编辑
问题不在AsyncTask本身,但是它并没有从网上获取电影数据API,而是问题与这里使用的Fragment有关,调试器没有识别类型的异常,但我可以确定它没有连接到服务器,因此,返回的 InputStream、StringBuffer 和 JsonString 是空值。
当在我的 activity class 文件的 onCreate 方法上初始化 recyclerview 时,相同的代码工作正常,但在片段上,应用程序崩溃而没有获得 Json 字符串从 API 请求的数组。它在异步任务中崩溃。任何关于问题出在哪里以及需要执行什么才能成功显示 recyclerview 的指示都将受到赞赏。提前致谢。
第二次编辑
E/dalvikvm: **Could not find class 'android.util.ArrayMap'**, referenced from method com.android.tools.fd.runtime.MonkeyPatcher.monkeyPatchExistingResources
09-09 21:04:48.351 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve check-cast 2079 (Landroid/util/ArrayMap;) in Lcom/android/tools/fd/runtime/MonkeyPatcher;
09-09 21:04:48.351 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x1f at 0x0258
09-09 21:04:48.361 26794-26794/com.example.prof_mohamedatef.tabletfragments E/dalvikvm: Could not find class 'android.util.ArrayMap', referenced from method com.android.tools.fd.runtime.MonkeyPatcher.pruneResourceCacheandroid.app.Fragment.setAllowEnterTransitionOverlap, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 377: Landroid/app/Fragment;.setAllowEnterTransitionOverlap (Z)V
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x03d8
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments I/dalvikvm: **Could not find method android.app.Fragment.onInflate**, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 358: Landroid/app/Fragment;.onInflate (Landroid/content/Context;Landroid/util/AttributeSet;Landroid/os/Bundle;)V
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x0468
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments I/dalvikvm: Could not find method android.app.Fragment.getEnterTransition, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 311: Landroid/app/Fragment;.getEnterTransition ()Landroid/transition/Transition;
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x0499
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments E/dalvikvm: **Could not find class 'android.transition.Transition', referenced from method** com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve check-cast 2075 (Landroid/transition/Transition;) in Lcom/example/prof_mohamedatef/tabletfragments/MainFragment;
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x1f at 0x04b5
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments I/dalvikvm: Could not find method **android.app.Fragment.getAllowEnterTransitionOverlap**, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 306: Landroid/app/Fragment;.getAllowEnterTransitionOverlap ()Z
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x04c9
注意那些粗体行,这是什么意思,这是我可以从 logCat 中的这次崩溃中得到的唯一参考。并且没有其他异常类型。
第三次编辑
09-11 14:25:14.968 3547-3714/com.example.prof_mohamedatef.tabletfragments E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.prof_mohamedatef.tabletfragments, PID: 3547
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
at java.net.InetAddress.lookupHostByName(InetAddress.java:464)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:175)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:125)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
at libcore.io.Posix.android_getaddrinfo(Native Method)
at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
at java.net.InetAddress.lookupHostByName(InetAddress.java:451)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:175)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:125)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: android_getaddrinfo failed: EACCES (Permission denied)
at libcore.io.Posix.android_getaddrinfo(Native Method)
at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
at java.net.InetAddress.lookupHostByName(InetAddress.java:451)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:175)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:125)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
解决方法 正是在这行错误中:
Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
错误非常简单:
Could not find class 'android.util.ArrayMap 表示编译器找不到它需要的 android classes。这不是您推理或代码中的错误,而是设置问题。仔细检查:
- 你的SDK路径是正确的
- 您的库和 SDK 级别已更新(在 SDK 管理器中)
- 在应用程序的 build.gradle 上,您的 defaultConfig 目标和编译至少 API 级别 20。
- 如果您使用的是 appcompat 库,请将所有缺失的 class 中的导入从
import android.util.ArrayMap;
更改为 import android.support.v4.util.ArrayMap;
。
让我知道它是否有效
我的清单中缺少互联网许可,只需添加:
<uses-permission android:name="android.permission.INTERNET" />
然后一切都会正常工作
以下所有代码都在 activity 上正常工作,但在尝试使用 Fragment 后,调试器显示它首先尝试调用 Fragment,然后尝试执行 AsyncTask class 不正确,它崩溃并且没有从 API 获得输入流值。我搜索了与我的问题相关的不同文章,但如果你愿意,我想在这里听取建议,这是我的代码如下:
activity_main.xml 文件代码行(其中包含片段将被添加或替换的容器):
<?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:id="@+id/mainactivity_container"
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"
android:orientation="vertical"
tools:context="com.example.prof_mohamedatef.tabletfragments.MainActivity">
</LinearLayout>
main_fragment.xml 文件代码行:
<?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="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/card_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity java 文件中的activity Container 与MainFragment 布局之间的beginTransaction 如下:
package com.example.prof_mohamedatef.tabletfragments;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainFragment mainFragment=new MainFragment();
getFragmentManager().beginTransaction()
.add(R.id.mainactivity_container,mainFragment)
.commit();
}
}
MainFragment java 文件正在 activity 上膨胀:
package com.example.prof_mohamedatef.tabletfragments;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
/**
* Created by Prof-Mohamed Atef on 9/8/2016.
*/
public class MainFragment extends android.app.Fragment{
private static final String TAG = "RecyclerViewFragment";
public MainFragment() {}
RecyclerView mRecyclerView;
public ImagesAdapter mAdapter;
ArrayList<MovieEntity> list = new ArrayList<MovieEntity>();
final String now = "http://api.themoviedb.org/3/movie/popular?api_key=868bebbf76a3831f11b3985c703cf959";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
update_START();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View rootView=inflater.inflate(R.layout.main_fragment,container,false);
rootView.setTag(TAG);
mRecyclerView = (RecyclerView)rootView.findViewById(R.id.card_recycler_view);
// mRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), 2);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
private void update_START() {
Fetch_Moview_data f_m_data = new Fetch_Moview_data();
f_m_data.execute(now);
}
public String main_List = "results";
public String POSTER_PATH = "poster_path";
public String VIDEO_ID = "id";
public String TITLE = "title";
public String OVERVIEW = "overview";
public String RELEASE_DATE = "release_date";
public String POPULARITY = "popularity";
public String VOTE_AVERAGE_="vote_average";
public String POSTER_PATH_STRING;
public String VIDEO_ID_STRING;
public String TITLE_STRING;
public String OVERVIEW_STRING;
public String RELEASE_DATE_STRING;
public String POPULARITY_STRING;
public String VOTE_AVERAGE_STRING;
public JSONObject MoviesJson;
public JSONArray moviesDataArray;
public JSONObject oneMovieData;
public class Fetch_Moview_data extends AsyncTask<String, Void, ArrayList<MovieEntity>> {
private final String LOG_TAG = Fetch_Moview_data.class.getSimpleName();
private ArrayList<MovieEntity> getMovieDataFromJson(String MoviesJsonStr)
throws JSONException {
MoviesJson = new JSONObject(MoviesJsonStr);
moviesDataArray = MoviesJson.getJSONArray(main_List);
list.clear();
for (int i = 0; i < moviesDataArray.length(); i++) {
// Get the JSON object representing a movie per each loop
oneMovieData = moviesDataArray.getJSONObject(i);
POSTER_PATH_STRING = oneMovieData.getString(POSTER_PATH);
VIDEO_ID_STRING = oneMovieData.getString(VIDEO_ID);
TITLE_STRING = oneMovieData.getString(TITLE);
OVERVIEW_STRING = oneMovieData.getString(OVERVIEW);
RELEASE_DATE_STRING = oneMovieData.getString(RELEASE_DATE);
POPULARITY_STRING = oneMovieData.getString(POPULARITY);
VOTE_AVERAGE_STRING=oneMovieData.getString(VOTE_AVERAGE_);
mAdapter=null;
MovieEntity entity = new MovieEntity(POSTER_PATH_STRING, VIDEO_ID_STRING, TITLE_STRING, OVERVIEW_STRING, RELEASE_DATE_STRING, POPULARITY_STRING,VOTE_AVERAGE_STRING);
list.add(entity);
}
return list;
}
@Override
protected ArrayList<MovieEntity> doInBackground(String... params) {
String Movies_images_JsonSTR = null;
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
if (params.length == 0) {
return null;
}
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
Movies_images_JsonSTR = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
Movies_images_JsonSTR = buffer.toString();
Log.v(LOG_TAG, "Movies JSON String: " + Movies_images_JsonSTR);
} catch (IOException e) {
Log.e(LOG_TAG, "Error here Exactly ", e);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}else {
Log.v(LOG_TAG, "Reader = null ( No Input Stream ) ");
}
}
try {
return getMovieDataFromJson(Movies_images_JsonSTR);
} catch (JSONException e) {
Log.e(LOG_TAG, "didn't got Movies Data from getJsonData method", e);
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ArrayList<MovieEntity> result) {
mAdapter=null;
list=result;
mAdapter = new ImagesAdapter(getContext(), result);
mRecyclerView.setAdapter(mAdapter);
}
}
}
编辑 问题不在AsyncTask本身,但是它并没有从网上获取电影数据API,而是问题与这里使用的Fragment有关,调试器没有识别类型的异常,但我可以确定它没有连接到服务器,因此,返回的 InputStream、StringBuffer 和 JsonString 是空值。
当在我的 activity class 文件的 onCreate 方法上初始化 recyclerview 时,相同的代码工作正常,但在片段上,应用程序崩溃而没有获得 Json 字符串从 API 请求的数组。它在异步任务中崩溃。任何关于问题出在哪里以及需要执行什么才能成功显示 recyclerview 的指示都将受到赞赏。提前致谢。
第二次编辑
E/dalvikvm: **Could not find class 'android.util.ArrayMap'**, referenced from method com.android.tools.fd.runtime.MonkeyPatcher.monkeyPatchExistingResources
09-09 21:04:48.351 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve check-cast 2079 (Landroid/util/ArrayMap;) in Lcom/android/tools/fd/runtime/MonkeyPatcher;
09-09 21:04:48.351 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x1f at 0x0258
09-09 21:04:48.361 26794-26794/com.example.prof_mohamedatef.tabletfragments E/dalvikvm: Could not find class 'android.util.ArrayMap', referenced from method com.android.tools.fd.runtime.MonkeyPatcher.pruneResourceCacheandroid.app.Fragment.setAllowEnterTransitionOverlap, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 377: Landroid/app/Fragment;.setAllowEnterTransitionOverlap (Z)V
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x03d8
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments I/dalvikvm: **Could not find method android.app.Fragment.onInflate**, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 358: Landroid/app/Fragment;.onInflate (Landroid/content/Context;Landroid/util/AttributeSet;Landroid/os/Bundle;)V
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x0468
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments I/dalvikvm: Could not find method android.app.Fragment.getEnterTransition, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 311: Landroid/app/Fragment;.getEnterTransition ()Landroid/transition/Transition;
09-09 21:04:49.061 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x0499
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments E/dalvikvm: **Could not find class 'android.transition.Transition', referenced from method** com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve check-cast 2075 (Landroid/transition/Transition;) in Lcom/example/prof_mohamedatef/tabletfragments/MainFragment;
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x1f at 0x04b5
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments I/dalvikvm: Could not find method **android.app.Fragment.getAllowEnterTransitionOverlap**, referenced from method com.example.prof_mohamedatef.tabletfragments.MainFragment.access$super
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments W/dalvikvm: VFY: unable to resolve virtual method 306: Landroid/app/Fragment;.getAllowEnterTransitionOverlap ()Z
09-09 21:04:49.071 26794-26794/com.example.prof_mohamedatef.tabletfragments D/dalvikvm: VFY: replacing opcode 0x6f at 0x04c9
注意那些粗体行,这是什么意思,这是我可以从 logCat 中的这次崩溃中得到的唯一参考。并且没有其他异常类型。
第三次编辑
09-11 14:25:14.968 3547-3714/com.example.prof_mohamedatef.tabletfragments E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.prof_mohamedatef.tabletfragments, PID: 3547
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
at java.net.InetAddress.lookupHostByName(InetAddress.java:464)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:175)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:125)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
at libcore.io.Posix.android_getaddrinfo(Native Method)
at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
at java.net.InetAddress.lookupHostByName(InetAddress.java:451)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:175)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:125)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: android_getaddrinfo failed: EACCES (Permission denied)
at libcore.io.Posix.android_getaddrinfo(Native Method)
at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
at java.net.InetAddress.lookupHostByName(InetAddress.java:451)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:175)
at com.example.prof_mohamedatef.tabletfragments.MainFragment$Fetch_Movies_data.doInBackground(MainFragment.java:125)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
解决方法 正是在这行错误中:
Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
错误非常简单: Could not find class 'android.util.ArrayMap 表示编译器找不到它需要的 android classes。这不是您推理或代码中的错误,而是设置问题。仔细检查:
- 你的SDK路径是正确的
- 您的库和 SDK 级别已更新(在 SDK 管理器中)
- 在应用程序的 build.gradle 上,您的 defaultConfig 目标和编译至少 API 级别 20。
- 如果您使用的是 appcompat 库,请将所有缺失的 class 中的导入从
import android.util.ArrayMap;
更改为import android.support.v4.util.ArrayMap;
。
让我知道它是否有效
我的清单中缺少互联网许可,只需添加:
<uses-permission android:name="android.permission.INTERNET" />
然后一切都会正常工作