意图putExtra方法的最大长度? (强制closures)
我需要一些帮助来debugging我的应用程序。 首先:在模拟器和其他一些设备上,我的应用运行良好。 在我的设备上,我得到了一个closures力量(没有强制closures信息)。
如果应用程序的“活动”发生更改,则会发生“崩溃”。
这里是MainActivity
类的一些代码。 它只是通过webview从网页上读取html内容。 不,不可能通过HttpRequest
做到这一点,因为我无法模拟发布请求。
public class MainActivity extends Activity { public final static String EXTRA_HTML = "com.example.com.test.HTML"; private WebView mWebView; private ProgressDialog mDialog; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.webView1); CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.removeAllCookie(); mWebView.setBackgroundColor(0); mWebView.setWebChromeClient(new WebChromeClient() { public boolean onConsoleMessage(ConsoleMessage cmsg) { if (cmsg.message().startsWith("MAGIC")) { mDialog.cancel(); /*HashMap<String, String> message = new HashMap<String, String>();*/ String msg = cmsg.message().substring(5); Intent intent = new Intent(MainActivity.this, ReadDataActivity.class); /*message.put("message", msg);*/ /*intent.putExtra(EXTRA_HTML, message);*/ intent.putExtra(EXTRA_HTML, msg); startActivity(intent); } return false; } }); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setPluginState(PluginState.OFF); mWebView.getSettings().setLoadsImagesAutomatically(false); mWebView.getSettings().setBlockNetworkImage(true); mWebView.getSettings().setAppCacheEnabled(true); mWebView.getSettings().setSavePassword(true); mWebView.getSettings() .setCacheMode(WebSettings.LOAD_NORMAL); mWebView.setWebViewClient(new WebViewClient() { public void onPageFinished(WebView view, String address) { if (address.indexOf("mySession") != -1) { view.loadUrl("javascript:console.log('MAGIC'+document.getElementsByTagName('html')[0].innerHTML);"); } }); mWebView.loadUrl("http://www.myurl.de"); }
所以,在onConsoleMessage()
方法中,我只是将HTML代码传递给另一个Activity类,它读取,parsing和显示内容。
现在的问题是,在此时应该加载ReadDataActivity
类,应用程序就会closures,并返回到主屏幕,而不需要任何消息或用户对话框。
是否有可能是作为一个string传递给ReadDataActivity
的HTML代码是大? 我也尝试添加一个HashMap中的string的HTML代码,但问题是一样的。
一些想法,我可以做些什么来debugging这个问题? 也许我应该尝试创build一个Parcelable
对象?
在模拟器中一切工作正常。
问候,桑德罗
根据我的经验(前一段时间),您可以在封装在Intent
中的Bundle
放置1MB的数据。 我想,这个限制是有效的,直到Froyo或GingerBread 。
但是,为了解决这个问题,我build议你将你的内容保存在一个临时文件中,然后把临时文件的path/ URI传递给你的第二个活动。 然后在第二个活动中,从文件中读出内容,执行所需的操作,最后删除该文件。
如果你愿意的话,你也可以为这个任务joinShared_Preferences – 如果你认为处理文件是麻烦的。
我对使用Intent可以传输的最大数据量做了一些研究。 而且这个限制似乎远不及1MB或90KB,更像是500KB (API 10,16,19和23testing)。
我写了一篇关于这个话题的博客文章,你可以在这里find它: https : //www.neotechsoftware.com/blog/android-intent-size-limit
1MB的固定大小不仅限于意图。由Intent,Content Provider,Messenger,电话,振动器等所有系统服务通过Binder使用IPC基础设施提供者。此外,活动生命周期callback也使用此基础设施。
1MB是系统在特定时刻执行的所有绑定事务的总体限制。
如果在发送意图时发生大量事务,即使额外的数据量不大,也可能会失败。 http://codetheory.in/an-overview-of-android-binder-framework/
在Jelly Bean中 ,Intent的大小限制还是相当低,比1MB(90K左右)还要低,所以即使你的应用只针对最新的Android版本,也应该对数据长度保持谨慎。
比赛迟到了一点,但是我碰到了同样的问题。 把数据写入文件在我的情况下并没有什么意义,但我在search答案时遇到了这个问题:
http://developer.android.com/guide/faq/framework.html#3
使用单例对我来说更好,因为不需要磁盘IO。 如果数据不需要保持,性能更好。
这是一个示例实现:
public class DataResult { private static DataResult instance; private List<SomeObject> data = null; protected DataResult() { } public static DataResult getInstance() { if (instance == null) { instance = new DataResult(); } return instance; } public List<SomeObject> getData() { return data; } public void setData(List<SomeObject> data) { this.data = data; } }
然后你可以在一个活动中使用这个设置:
DataResult.getInstance().setData(data);
并在这样的其他活动:
List<SomeObject> data = DataResult.getInstance().getData();
在活动之间传递大量数据的另一种解决scheme是使用静态字段。 在你的情况下,将此行添加到ReadDataActivity类
public static String msg;
然后,您可以在MainActivity类中使用静态字段msg,如下所示
ReadDataActivity.msg = cmsg.message().substring(5);
最后开始你的活动没有额外的投入
Intent intent = new Intent(MainActivity.this, ReadDataActivity.class); startActivity(intent);
我已经看到,通过写入和读取文件组成的性能较差。 然后我看到了这个解决scheme: 。 所以我正在使用这个解决scheme:
public class ExtendedDataHolder { private static ExtendedDataHolder ourInstance = new ExtendedDataHolder(); private final Map<String, Object> extras = new HashMap<>(); private ExtendedDataHolder() { } public static ExtendedDataHolder getInstance() { return ourInstance; } public void putExtra(String name, Object object) { extras.put(name, object); } public Object getExtra(String name) { return extras.get(name); } public boolean hasExtra(String name) { return extras.containsKey(name); } public void clear() { extras.clear(); } }
然后在MainActivity中,我把它称为如下:
ExtendedDataHolder extras = ExtendedDataHolder.getInstance(); extras.putExtra("extra", new byte[1024 * 1024]); extras.putExtra("other", "hello world"); startActivity(new Intent(MainActivity.this, DetailActivity.class));
并在DetailActivity
ExtendedDataHolder extras = ExtendedDataHolder.getInstance(); if (extras.hasExtra("other")) { String other = (String) extras.getExtra("other"); }
活页夹事务缓冲区具有有限的固定大小 – 1Mb。 但是问题在于缓冲区在进程中正在进行的所有事务共享 。
所以尽量保持你的意图数据尽可能小。
使用static String
variables是很好的。 如果用户需要在不同的HTML之间来回切换,也可以像这样使用LruCache
:
static LruCache<String, String> mMemoryCache; final int kiloByte = 1024; . . final int maxMemoryKB = (int) (Runtime.getRuntime().maxMemory() / kiloByte); // then choose how much you want to allocate for cache final int cacheSizeKB = maxMemoryKB / 8; . . mMemoryCache = new LruCache<String, String>(cacheSizeKB) { //@Override protected int sizeOf(String key, String value) { try { byte[] bytesUtf8 = value.getBytes("UTF-8"); return bytesUtf8.length / kiloByte; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return -1; } }; . . String cacheKey = generateUniqueString(key); if (mMemoryCache.get(key) == null) { mMemoryCache.put(cacheKey, yourContent); } Intent intent = new Intent(getApplicationContext(), ReadDataActivity.class); intent.putExtra(EXTRA_HTML, cacheKey); startActivity(intent);
然后在ReadDataActivity
端
Intent intent = getIntent(); String cacheKey = intent.getStringExtra(EXTRA_HTML); String contentString = MainActivity.mMemoryCache.get(cacheKey); doSomethingWith(contentString);
这个想法来自这里 。