2016-07-19 45 views
0

我使用RestAPI獲取圖像位置,然後將其附加到適配器上並使用Recyclerview顯示數據。圖像存儲在服務器上而不是電話上。 Recyclerview運作良好,但圖像總是變化,當我嘗試快速滾動到數據的末尾時,它會被強制關閉並彈出像這樣使用RestAPI Android C#滾動時,RecyclerView上的圖像總是發生變化

「Java.Lang.OutOfMemoryError:未能分配2380812字節直到OOM爲止,分配976640個空閒字節和953KB「。

Here是我的應用如何工作的視頻。

這裏是我的代碼,這是我的適配器CrewMemberRecyclerViewAdapter.cs:

using System; 
using System.Collections.Generic; 
using Android.Graphics; 
using Android.Support.V7.Widget; 
using Android.Views; 
using Ardiles_App.Resources; 
using System.Net; 

namespace my_APP 
{ 
    public class CrewMemberRecyclerViewAdapter : RecyclerView.Adapter 
    { 
     //Create an Event so that our our clients can act when a user clicks 
     //on each individual item. 
     public event EventHandler<int> ItemClick; 

     private List<CrewMember> _crewMembers; 
     private readonly ImageManager _imageManager; 

     public CrewMemberRecyclerViewAdapter(List<CrewMember> crewMembers, Android.Content.Res.Resources resources) 
     { 
      _crewMembers = crewMembers; 
      _imageManager = new ImageManager(resources); 
     } 

     //Must override, just like regular Adapters 
     public override int ItemCount 
     { 
      get 
      { 
       return _crewMembers.Count; 
      } 
     } 

     //Must override, this inflates our Layout and instantiates and assigns 
     //it to the ViewHolder. 
     public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) 
     { 
      //Inflate our CrewMemberItem Layout 
      View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.DetailItem, parent, false); 

      //Create our ViewHolder to cache the layout view references and register 
      //the OnClick event. 
      var viewHolder = new CrewMemberItemViewHolder(itemView, OnClick); 

      return viewHolder; 
     } 

     //Must override, this is the important one. This method is used to 
     //bind our current data to your view holder. Think of this as the equivalent 
     //of GetView for regular Adapters. 
     public override async void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) 
     { 
      var viewHolder = holder as CrewMemberItemViewHolder; 

      var currentCrewMember = _crewMembers[position]; 

      //Bind our data from our data source to our View References 
      viewHolder.CrewMemberName.Text = currentCrewMember.nama; 
      viewHolder.RankAndPosting.Text = String.Format("{0}\n{1}", "Rp." + currentCrewMember.harga, currentCrewMember.bahan); 

      //INI FOTO SEPATU 
      string linkGambar = "http://my.server.com/example/images/" + currentCrewMember.fotou; 
      Bitmap _bimage; 
      // _bimage = GetImageBitmapFromUrl(linkGambar); 

      var webClient = new WebClient(); 
      var imageBytes = await webClient.DownloadDataTaskAsync(new Uri(linkGambar)); 
      _bimage = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length); 

      BitmapFactory.Options option = new BitmapFactory.Options(); 
      option.InBitmap = _bimage; 
      Bitmap _bfinal; 
      _bfinal = getRoundedShape(_bimage, 150, 150); 
      //var photoBitmap = await _imageManager.GetScaledDownBitmapFromResourceAsync(currentCrewMember.PhotoResourceId, 120, 120); 
      viewHolder.CrewMemberPhoto.SetImageBitmap(_bfinal); 
     } 

     //This will fire any event handlers that are registered with our ItemClick 
     //event. 
     private void OnClick(int position) 
     { 
      if (ItemClick != null) 
      { 
       ItemClick(this, position); 
      } 
     } 

     //Since this example uses a lot of Bitmaps, we want to do some house cleaning 
     //and make them available for garbage collecting as soon as possible. 
     protected override void Dispose(bool disposing) 
     { 
      base.Dispose(disposing); 

      if (_imageManager != null) 
      { 
       _imageManager.Dispose(); 
      } 

     } 
     public Bitmap getRoundedShape(Bitmap scaleBitmapImage, int width, int height) 
     { 
      int targetWidth = width; 
      int targetHeight = height; 
      Bitmap targetBitmap = Bitmap.CreateBitmap(targetWidth, 
       targetHeight, Bitmap.Config.Argb8888); 

      Canvas canvas = new Canvas(targetBitmap); 
      /* 
      Android.Graphics.Path path = new Android.Graphics.Path(); 
      path.AddCircle(((float)targetWidth - 1)/2, 
       ((float)targetHeight - 1)/2, 
       (Math.Min(((float)targetWidth), 
        ((float)targetHeight))/2), 
       Android.Graphics.Path.Direction.Ccw);*/ 

      // canvas.ClipPath(path); 
      Bitmap sourceBitmap = scaleBitmapImage; 
      canvas.DrawBitmap(sourceBitmap, 
       new Rect(0, 0, sourceBitmap.Width, 
        sourceBitmap.Height), 
       new Rect(0, 0, targetWidth, targetHeight), null); 
      return targetBitmap; 
     } 
    } 
} 

這是CrewManifest.cs

using System.Collections.Generic; 
using Android.Content; 
using System.Net; 
using System.Threading.Tasks; 
using System.IO; 
using Newtonsoft.Json; 

namespace my_APP 
{ 
    public class CrewManifest 
    { 
     public static async Task<List<CrewMember>> GetAllCrewAsync(string kategori) 
     { 
      string url = "http://my.server.com/example/API/" + kategori; 
      List<CrewMember> crewList = JsonConvert.DeserializeObject<List<CrewMember>>(await FetchUserAsync(url)); 
      return crewList; 
     } 

     private static async Task<string> FetchUserAsync(string url) 
     { 

      // Create an HTTP web request using the URL: 
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); 
      request.ContentType = "application/json"; 
      request.Method = "GET"; 

      // Send the request to the server and wait for the response: 
      using (WebResponse response = await request.GetResponseAsync()) 
      { 
       // Get a stream representation of the HTTP web response: 
       using (var sr = new StreamReader(response.GetResponseStream())) 
       { 
        string strContent = sr.ReadToEnd(); 
        return strContent; 
       } 
      } 
     } 
    } 
} 

這是我的課

public class CrewMember 
    { 
     public string no { get; set; } 
     public string nama { get; set; } 
     public string uk { get; set; } 
     public string fotou { get; set; } 
     public string bahan { get; set; } 
     public string poin { get; set; } 
     public string harga { get; set; } 
     public string warna1 { get; set; } 
     public string warna2 { get; set; } 
     public string warna3 { get; set; } 
     public string warna4 { get; set; } 
     public string warna5 { get; set; } 
    } 

這是我的JSON數據:

[{"no":"167","nama":"Elok","uk":"36- 40","fotou":"167-1.jpg","bahan":"","poin":"50","harga":"61800.00","warna1":"Black","warna2":"Burgundy","warna3":"Brown","warna4":"Violet","warna5":null},{"no":"168","nama":"Glow","uk":"37- 40","fotou":"168-1.jpg","bahan":"","poin":"60","harga":"60800.00","warna1":"","warna2":"","warna3":"Brown","warna4":"Violet","warna5":null},{"no":"169","nama":"Hera","uk":"37- 40","fotou":"169-1.jpg","bahan":"","poin":"60","harga":"62800.00","warna1":"","warna2":"","warna3":"Brown","warna4":"Violet","warna5":null},{"no":"170","nama":"Kilau","uk":"32- 35","fotou":"170-1.jpg","bahan":"","poin":"50","harga":"53800.00","warna1":"","warna2":"","warna3":"Brown","warna4":"Violet","warna5":null},{"no":"171","nama":"Sari","uk":"37- 40","fotou":"171-1.jpg","bahan":"","poin":"60","harga":"62800.00","warna1":"","warna2":"","warna3":"Brown","warna4":"Violet","warna5":null},{"no":"172","nama":"Xena","uk":"36- 40","fotou":"172-1.jpg","bahan":"","poin":"50","harga":"54800.00","warna1":"Red","warna2":"","warna3":"Brown","warna4":"Violet","warna5":null}] 

我正在使用Visual Studio 2015和Xamarin來構建此應用程序。 在此先感謝

回答

1

嘗試使用一些圖片緩存庫,用於獲取圖像...

https://components.xamarin.com/view/square.picasso

用法:

Picasso.With(context) 
     .Load("http://i.imgur.com/DvpvklR.png") 
     .Into(imageView); 

如果妳需要調整圖像使用.Resize(50, 50)

Picasso.With(context) 
     .Load(url) 
     .Resize(50, 50) 
     .Into(imageView); 

我認爲你應該閱讀一些在Android開發者頁面,特別是在這裏:Displaying Bitmaps Efficiently

+0

謝謝,形象不會再改變,但第二個問題依然存在。此錯誤消息「Java.Lang.OutOfMemoryError:未能分配2380812字節分配,976640空閒字節和953KB直到OOM」。 – neneo

+0

問題解決了! 我的圖片尺寸太大,所有的圖片都會一一調整大小,這會使得圖片處理過程變得很複雜。 – neneo

相關問題