使用 HttpResponseCache 会使应用程序崩溃
Posted
技术标签:
【中文标题】使用 HttpResponseCache 会使应用程序崩溃【英文标题】:Using HttpResponseCache makes app crash 【发布时间】:2016-03-26 05:00:21 【问题描述】:我正在尝试使用 HttpResponseCache 来缓存网络数据,但是当我将安装缓存代码放入 OnCreate 和 OnPause 方法时,应用崩溃。 我使用了来自HttpResponseCache documentation 的代码。并出现如下所示的编译错误。使用后
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
为了解决它消失的错误,我运行应用程序但仍然崩溃。 当我删除该代码时,它会恢复正常行为。
protected void onCreate(Bundle savedInstanceState)
...
try
File httpCacheDir = new File(context.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize); //error
catch (IOException e)
Log.i(TAG, "HTTP response cache installation failed:" + e);
protected void onStop()
...
HttpResponseCache cache = HttpResponseCache.getInstalled();//error
if (cache != null)
cache.flush();//error
我是初学者,如果有人能提供帮助,我将不胜感激。 这是 MainActivity 代码
public class MainActivity extends AppCompatActivity
private MovieAdapter movieAdapter;
private Context context;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ------ caching data ------------------
try
File httpCacheDir = new File(context.getCacheDir(), "http");
long httpCacheSize = 2 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize); //error
catch (IOException e)
Log.i("caching failed", "HTTP response cache installation failed:" + e);
//-----------------------
DataSyncTask dataSyncTask = new DataSyncTask();
dataSyncTask.execute();
@Override
public boolean onCreateOptionsMenu(Menu menu)
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
int id = item.getItemId();
if (id == R.id.action_settings)
startActivity(new Intent(this, SettingsActivity.class));
return true;
return super.onOptionsItemSelected(item);
private class DataSyncTask extends AsyncTask<Void, Void, ArrayList<Movie>>
@Override
protected ArrayList<Movie> doInBackground(Void... params)
JSONHttpClient jsonHttpClient = new JSONHttpClient(MainActivity.this);
JSONDataParser finalData = new JSONDataParser();
/*
using shared preference to obtain data
*/
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String sortingOrder = sharedPreferences.getString(
getString(R.string.pref_findMovies_key),
getString(R.string.pref_popular_value));
String streamData = jsonHttpClient.getData(sortingOrder);
return finalData.getParsedData(streamData);
@Override
protected void onPostExecute(final ArrayList<Movie> movies)
movieAdapter = new MovieAdapter(getApplicationContext(), movies);
GridView gridView = (GridView) findViewById(R.id.movies_grid);
gridView.setAdapter(movieAdapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
Movie movie = (Movie) adapterView.getItemAtPosition(i);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("MovieTitle", movie.getTitle());
intent.putExtra("voteAverage", movie.getVoteAverage());
intent.putExtra("ReleaseDate", movie.getReleaseDate());
intent.putExtra("MovieOverview", movie.getOverview());
intent.putExtra("PosterPath", movie.getPosterPath());
startActivity(intent);
);
@Override
protected void onResume()
DataSyncTask dataSyncTask = new DataSyncTask();
dataSyncTask.execute();
super.onResume();
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
protected void onStop()
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null)
cache.flush();
super.onStop();
应用崩溃后出现在 logcat 中的内容
12-19 19:22:58.465 17548-17548/com.example.geekymind.displayjsondatafrominternet W/dalvikvm﹕ VFY: unable to find class referenced in signature (Landroid/view/SearchEvent;)
12-19 19:22:58.465 17548-17548/com.example.geekymind.displayjsondatafrominternet I/dalvikvm﹕ Could not find method android.view.Window$Callback.onSearchRequested, referenced from method android.support.v7.internal.view.WindowCallbackWrapper.onSearchRequested
12-19 19:22:58.465 17548-17548/com.example.geekymind.displayjsondatafrominternet W/dalvikvm﹕ VFY: unable to resolve interface method 14585: Landroid/view/Window$Callback;.onSearchRequested (Landroid/view/SearchEvent;)Z
12-19 19:22:58.465 17548-17548/com.example.geekymind.displayjsondatafrominternet I/dalvikvm﹕ Could not find method android.view.Window$Callback.onWindowStartingActionMode, referenced from method android.support.v7.internal.view.WindowCallbackWrapper.onWindowStartingActionMode
12-19 19:22:58.465 17548-17548/com.example.geekymind.displayjsondatafrominternet W/dalvikvm﹕ VFY: unable to resolve interface method 14589: Landroid/view/Window$Callback;.onWindowStartingActionMode (Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
12-19 19:22:58.505 17548-17548/com.example.geekymind.displayjsondatafrominternet I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations
12-19 19:22:58.505 17548-17548/com.example.geekymind.displayjsondatafrominternet W/dalvikvm﹕ VFY: unable to resolve virtual method 451: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
12-19 19:22:58.515 17548-17548/com.example.geekymind.displayjsondatafrominternet I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType
12-19 19:22:58.515 17548-17548/com.example.geekymind.displayjsondatafrominternet W/dalvikvm﹕ VFY: unable to resolve virtual method 473: Landroid/content/res/TypedArray;.getType (I)I
12-19 19:22:58.585 17548-17548/com.example.geekymind.displayjsondatafrominternet W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x415ffc80)
【问题讨论】:
错误信息在哪里? @Orlangure 我刚加了,希望清楚什么问题 【参考方案1】:根据HttpResponseCache Docs:
通过以下方式启用对应用程序的所有 HTTP 请求的缓存 在应用程序启动时安装缓存。
所以你应该使用如下:
MyApplication.java:
public class MyApplication extends Application
private final Context mContext = this;
public void onCreate()
super.onCreate();
// Install the cache
try
File httpCacheDir = new File(mContext.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
catch (IOException e)
Log.i("CacheHttpUrlConnection", "HTTP response cache installation failed:" + e);
// Register for activity lifecycle callbacks,
// specifically interested in activity stop callbacks.
registerActivityLifecycleCallbacks(
new MyApplicationActivityLifeCycleCallbacks());
// method to flush cache contents to the filesystem
public void flushCache()
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null)
cache.flush();
private class MyApplicationActivityLifeCycleCallbacks implements ActivityLifecycleCallbacks
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState)
@Override
public void onActivityStarted(Activity activity)
@Override
public void onActivityResumed(Activity activity)
@Override
public void onActivityPaused(Activity activity)
public void onActivityStopped(Activity activity)
flushCache();
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState)
@Override
public void onActivityDestroyed(Activity activity)
MainActivity.java:
在AsyncTask
类的doInBackground
内:
...
URL url = new URL(address);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
urlConnection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);
// Checks cache
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
cache = HttpResponseCache.getInstalled();
if (cache != null)
cacheInfo = "Request count: "
+ cache.getRequestCount() + ", hit count "
+ cache.getHitCount() + ", network count "
+ cache.getNetworkCount() + " size = "
+ cache.size() + " <-----------------";
Log.i(LOG_TAG, cacheInfo);
// Gets stream
Log.i(LOG_TAG, "RespCode: " + urlConnection.getResponseCode());
if (urlConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST)
inputStream = urlConnection.getInputStream();
else
inputStream = urlConnection.getErrorStream();
// Parses stream to string
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String temp, response = "";
while ((temp = bufferedReader.readLine()) != null)
response += temp;
...
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cachehttpurlconnection" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:name="com.example.cachehttpurlconnection.MyApplication" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
【讨论】:
以上是关于使用 HttpResponseCache 会使应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
HttpResponseCache 在 Android Lollipop 中不起作用
如何在 Android 上使用 HttpsURLConnection 和 HttpResponseCache 强制缓存?
将 LRU 图像缓存与 HTTPResponseCache 结合用于磁盘和内存缓存
java.lang.NoClassDefFoundError 与 HttpResponseCache 和 DiskLruCache