小部件更新的 RemoteViews 超出最大位图内存使用错误

Posted

技术标签:

【中文标题】小部件更新的 RemoteViews 超出最大位图内存使用错误【英文标题】:RemoteViews for widget update exceeds max bitmap memory usage error 【发布时间】:2012-11-09 19:13:08 【问题描述】:

我有一个小部件,它解析 xml 提要并显示其标题和图像。在这个小部件中,我使用定期更改内容(即标题和图像)的服务。为此,我使用计时器类。当我们运行时这个小部件,一些内容显示没有任何问题,但一段时间后它强制关闭并显示错误,如“用于小部件更新的远程视图超出最大位图内存使用量(已使用:2465280 最大值:2304000)总内存不能超过填充所需的内存设备的屏幕一次”。请有人帮我解决这个问题...在此先感谢

这是我的 AppwidgetProvider=>

 public class myappwidgetprovider extends AppWidgetProvider 
    public static String urls="http://www.abc.com/en/rssfeeds/9/latest/rss.xml";
    // XML node keys
    static final String KEY_HEAD = "item"; // parent node
    //static final String KEY_TITLE = "title";
    static final String KEY_DATE = "pubDate";
    public static String headflag="english";
    public static String[] Title;
        public static String[] Description;
        public static String[] Tit;
        public static String[] Tit2;
        public static String[] Desc;
        public static String[] Desc2;
        public static String[] image;
    public static TextView flashnews;

    public static int i=0;

     public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds )
        

         Log.i("Tag", "onCreateView");
         parse();


           RemoteViews remoteViews;
                        ComponentName thisWidget = new ComponentName(context,myappwidgetprovider .class);

                int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

                Intent intent = new Intent(context.getApplicationContext(),
                        Updatewidget.class);
                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
                            context.startService(intent);

               





     public static void parse()
     

            URL url;

            try 

                url = new URL(urls);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                if((conn.getResponseCode() == HttpURLConnection.HTTP_OK))
                      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                      DocumentBuilder db = dbf.newDocumentBuilder();
                      Document doc;
                      doc = db.parse(url.openStream());
                      doc.getDocumentElement().normalize();

                      NodeList itemLst = doc.getElementsByTagName("item");
                      Description = new String[itemLst.getLength()];//........
                      Title = new String[itemLst.getLength()];
                      Tit=new String[itemLst.getLength()];
                      Tit2=new String[itemLst.getLength()];
                      Desc=new String[itemLst.getLength()];
                      Desc2=new String[itemLst.getLength()];
                      image= new String[itemLst.getLength()];

                      for(int i=0; i < itemLst.getLength(); i++)

                            Node item = itemLst.item(i);
                            if(item.getNodeType() == Node.ELEMENT_NODE)
                                  Element ielem = (Element)item;
                                  NodeList title = ielem.getElementsByTagName("title");
                                  NodeList date = ielem.getElementsByTagName("pubDate");
                                  NodeList description = ielem.getElementsByTagName("description");
                                  Tit[i]= title.item(0).getChildNodes().item(0).getNodeValue();
                                  Desc[i]= description.item(0).getChildNodes().item(0).getNodeValue();
                                  Tit2[i]=Translate.title(Tit[i]);
                                  Desc2[i]=Translate.description(Desc[i]);
                                  if(headflag=="malayalam")
                                    
                                      Desc2[i]=Desc2[i].replace("read more","IqSpXÂ");
                                    
                                  Title[i] =Tit2[i];
                                  if (Desc2[i].contains("<img "))
                                      String img  = Desc2[i].substring(Desc2[i].indexOf("<img "));
                                      String cleanUp = img.substring(0, img.indexOf(">")+1);
                                      img = img.substring(img.indexOf("src=") + 5);
                                      int indexOf = img.indexOf("'");
                                      if (indexOf==-1)
                                          indexOf = img.indexOf("\"");
                                        
                                      img = img.substring(0, indexOf);

                                //setImgLink(img);
                                    if(headflag=="malayalam")
                                    
                                        String img2=img.replace("files","files/imagecache/android_320");
                                        Description[i]=Desc2[i].replace(img,img2);
                                        image[i]=img2;
                                    

                                else
                                
                                    String img2=img.replace("files","files/imagecache/android_1_img");
                                    Description[i]=Desc2[i].replace(img,img2);
                                    image[i]=img2;
                                
                                  
                                else
                                
                                    Description[i] =Desc2[i];
                                



                            

                          

                        
             catch (MalformedURLException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
             catch (DOMException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
             catch (ParserConfigurationException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
             catch (SAXException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
     


这是我的服务=>

public class Updatewidget extends Service 
    static String UPDATEMOOD ="UPDATEMOOD";
    public Intent newintent;
    public AppWidgetManager app;
    public RemoteViews newviews;
    public int[] newappid;
    int i=0;
    @Override
    public void onStart(final Intent intent, int startId) 

         Log.i("Tag", "Service Called!!!!!!!!!!!!!");

         newintent=intent;
                 int[] allWidgetIds = intent
                    .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
         newappid=allWidgetIds;

         final AppWidgetManager appWidgetMan = AppWidgetManager.getInstance(this);
         app=appWidgetMan;
         final RemoteViews views = new RemoteViews(this.getPackageName(),R.layout.widget_main);
         newviews=views;
         views.setTextViewText(R.id.title, myappwidgetprovider.Title[0]);
         Bitmap bitmap;
            try 
                bitmap = BitmapFactory.decodeStream((InputStream)new URL(myappwidgetprovider.image[0]).getContent());


                views.setImageViewBitmap(R.id.imageView4, bitmap);
             catch (MalformedURLException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
         appWidgetMan.updateAppWidget(allWidgetIds, views); 

         new ProgressAsyncTask().execute();








    



     public class ProgressAsyncTask extends 
        AsyncTask<Void, Integer, Void> 

        @Override
        protected Void doInBackground(Void... params) 
            // TODO Auto-generated method stub
             int delay = 5000; // delay for 5 sec.

             int period = 5000; // repeat every sec.

             Timer timer = new Timer();
              timer.scheduleAtFixedRate(new TimerTask() 

                     public void run() 
                         i++;
                         if(i==5)
                         
                             i=0;
                         

                         int[] allWidgetIds = newintent
                                    .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                                 newviews.setTextViewText(R.id.title, myappwidgetprovider .Title[i]);
                         Bitmap bitmap;
                            try 
                                bitmap = BitmapFactory.decodeStream((InputStream)new URL(myappwidgetprovider .image[i]).getContent());


                                newviews.setImageViewBitmap(R.id.imageView4, bitmap);
                             catch (MalformedURLException e) 
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                             catch (IOException e) 
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            
                         app.updateAppWidget(allWidgetIds, newviews); 
                                 


                     , delay, period);
            return null;
        
     

    @Override
    public IBinder onBind(Intent intent) 
        // TODO Auto-generated method stub
        return null;
    






【问题讨论】:

【参考方案1】:

我刚刚解决了一个类似的问题。 但我没有从网络加载任何内容。 我的小部件针对不同的小部件尺寸显示不同的图像。对于某些屏幕,显示小部件 4x4 时会出现与您相同的错误。

这是我在 developer.google.com 上找到的:

RemoteViews 对象使用的总 Bitmap 内存不能超过 需要填充屏幕 1.5 倍,即。 (屏幕宽度 x 屏幕 高度 x 4 x 1.5) 字节。

所以我可以在小部件中限制我的位图大小以满足此要求。

在您的特定情况下,当从流中加载的位图超出可能时会发生错误。

我认为

的用法

public static Bitmap decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options 选项)

使用适当的选项应该会有所帮助。 (可能您需要使用 inSampleSize 选项)。

希望我的帖子对您​​有所帮助。

【讨论】:

我想我已经解决了这个问题。无论如何,谢谢你:) @Rusanovskiy Artem:你怎么知道要传递给decodeStream() 的确切选项?如果您在小部件中有四个位图,并且您不知道源图像的大小,您怎么知道您必须使用哪个sampleSize 来防止Exception @BasimSherif 你能解释一下你是如何解决这个问题的吗?谢谢!【参考方案2】:
    Glide.with(mContext)
        .load(imageUrl)
        .override(480, 342)

....

override(...) 为我解决了问题。 没有更多错误,例如: 小部件更新的 RemoteViews 超出最大位图内存使用错误

【讨论】:

以上是关于小部件更新的 RemoteViews 超出最大位图内存使用错误的主要内容,如果未能解决你的问题,请参考以下文章

Android:将位图从本地存储加载到应用小部件(RemoteViews)

RemoteViews (Widget) 使用 Bitmap 时文本模糊

将位图动态放入小部件时失败的活页夹事务

Android appwidget remoteviews没有更新

为啥 AppWidgetManager 会更新所有 RemoteViews for Widgets 的 Intent?

Android Widget 膨胀布局性能和内存