Pro Yearly is on sale from $80 to $50! »

600件のPull RequestからみたXamarinのはまりどころ

600件のPull RequestからみたXamarinのはまりどころ

2016/05/07(Sat) Japan Xamarin User Group #13 Xamarinのすべて!

619fccc61ef955ccf39bfa41df527042?s=128

Nobuhiro Ito

May 07, 2016
Tweet

Transcript

  1. 600݅ͷPull Request ͔ΒΈͨ Xamarin ͸·ΓϙΠϯτ Nobuhiro Ito / Fenrir Inc.

    @ Japan Xamarin User Group Conference #13, 2016/05/07(Sat)
  2. @iseebi Nobuhiro Ito Fenrir Inc. Smartphone App Engineer http://iseebi.hatenablog.com/

  3. ձࣾͱͯ͠Xamarinྺ2೥൒Ҏ্ ా෵͞Μ͕XamarinऔΓѻ͍͸͡ΊΔલ͔Β΍ͬͯΔ

  4. MvvmCross Ψν੎ ͨͩ࠷ۙ͸΋ͬͱଞͷ΋ͷΛࢼ͍ͨ͠ͱࢥͬͯΔ… ※px୯ҐͰϨΠΞ΢τࢦ͕ࣔඈΜͰ͘ΔͷͰFormsͰ͸ରॲͰ͖ͳ͍

  5. ࠷ۙͷ͓࢓ࣄ ΞϓϦͷ։ൃͷ͔ͨΘΒɺύοέʔδ੡඼ͷϓϩμΫτΦʔφʔ΍ͬͯ·͢ɻ

  6. ͋ΔϓϩδΣΫτͷ͓࿩Λ͠·͢

  7. ϓϩδΣΫτͷ؅ཧମ੍ͷมԽ • 2011, 2012೥
 ωΠςΟϒ / Subversion (2012೥ͷ్த͔ΒgitҠߦ), Redmine •

    2013, 2014೥
 Xamarin / git, Redmine, Backlog, TeamGantt • 2015೥
 Xamarin / GitHub Enterprise, Redmine, Backlog, TeamGantt
  8. GitHub Enterprise ʹͯ͠Α͔ͬͨ͜ͱ • શ෦ Pull Request ͰϨϏϡʔͰ͖Δ • ͋ͱ͔Β༷ʑͳ͜ͱΛৼΓฦΔ͜ͱ͕Ͱ͖Δɻ

  9. ͋ͱ͔ΒৼΓฦΔ͜ͱ͕Ͱ͖Δ • ίϛοτͷճ਺ͱ͔ • ͲΜͳίϛοτΛ͔ͨ͠ͱ͔ (શ෦ Pull Request ͰݟΕΔ)

  10. None
  11. 4ϲ݄Ͱͪΐ͏ͲͽͬͨΓPR 600݅ ࠓ೔͸͜ͷத͔Β ಛʹʮۤ͠Μͩͳʔʯͱ͍͏ͱ͜ΖΛ ͔͍ͭ·ΜͰ͝঺հ

  12. ͦͷ1 HTTPϋϯυϥෆ҆ఆࣄ݅

  13. Hello, ModernHttpClient • աڈͷ։ൃ͔ΒɺHttpWebRequest ͩͱ Android Ͱ 
 ·Εʹ DNS

    ͕1෼΄ͲҾ͚ͳ͘ͳΓɺ௨৴Ͱ͖ͳ͘ͳΔ͜ͱ͕Θ͔͍ͬͯͨɻ • 2015೥͸ModernHttpClientΛ࢖͏͜ͱ͸ܾΊ͍ͯͨɻ • HttpClient ͷҾ਺ʹ౉͢ HttpClientHandler ͱͯ͠౉͢
 NativeMessageHandler Λఏڙͯ͘͠ΕΔɻ • iOS 9 ͷ ATS ରԠͱͯ͠΋ඞਢͩͬͨɻ
  14. iOS 8 ͔͋Μ΍Μ… • ModernHttpClient ͷಋೖࣗମ͸ΘΓͱ͢ΜͳΓͰ͖ͨɻ • AutomaticDecompression = true

    Λࢦఆ͍ͯ͠Δͱ
 iOS ͰΫϥογϡ͢Δͱ͔͸͋ͬͨɻ • ͔͠͠ɺࠓ౓͸ iOS 8 Ͱ HTTP ͕௨Βͳ͘ͳΔݱ৅͕ൃੜ͢Δ…
  15. CFNetworkHandler…ࠓ౓͸iOS9͕͔͋Μ… • ModernHttpClientಉ༷ʹɺHttpClientHandlerͱͯ͠࢖͑Δ System.Net.Http.CFNetworkHandler ͕ೖ͍ͬͯͨͷͰ࢖͏ɻ • iOS 8Ͱ͸҆ఆ͢Δ͕ɺiOS 9 Ͱ͸

    https ͕௨Βͳ͘ͳͬͨɻ • iOS 8 Ҏલ͸ CFNetworkHandlerɺ
 ͦΕҎ֎Ͱ͸ NativeMessageHandler Λ
 ࢖༻͢ΔΑ͏ʹ͢Δ͜ͱͰղܾɻ • NSUrlSessionHandler/AndroidClientHandler ͕ඪ४౥ࡌ͞Ε(Δ|ͨ)Β͍͠ͷͰظ଴ɻ J04PS&BSMJFS $'/FUXPSL)BOEMFS J04 /BUJWF.FTTBHF)BOEMFS "OESPJE /BUJWF.FTTBHF)BOEMFS
  16. ͦͷ2 Content Description จࣈԽ͚ࣄ݅ @Android

  17. ࣗಈςετ͠·͠ΐ͏…·͓ͨ·͔͑Galaxy! • Android ͷ UI ςετΛ͢Δ͜ͱʹͳ͍ͬͯͨͷͰɺContent Description Λࢦఆ͍ͯͨ͠ɻ • ೔ຊ୺຤ͷ඼ἧ͑ͷ໰୊Ͱ

    Xamarin Test Cloud Ͱ͸ͳ͘ɺ
 Remote TestKit ͱUIAutomator ͷ૊Έ߹Θͤɻ • ೔ຊޠͷ Content Description Λࢦఆ͍ͯ͠Δͱ
 Galaxy S6 edge Ͱ͜ͱ͝ͱ͘??????????????ʹจࣈԽ͚ɻ • ݁ہӳޠࢦఆ͠ɺϦϦʔεલʹ໭͢͜ͱͰղܾɻXTC ࢖ͬͯͯ΋໰୊ʹͳΔ͔΋ʁ
  18. ͦ΋ͦ΋GalaxyͱXamarinͷ૬ੑ͕ѱ͍ • جຊతʹԿ͔໰୊͋Δͷ͸ GalaxyɻS4, S5, S6 શ෦Ϡό͍ɻ • Galaxy S4

    4.2.1 ͕ಛʹϠό͍ɻଞͷ୺຤Ͱಈ͍͍ͯΔίʔυ͕ී௨ʹམͪΔɻ • ͦͯ͜͠ͷ୺຤͸ͳΜͱUSBσόοάͰ͖ͳ͍ʢʂʣ • ͨͩɺ͍͕ͭ͜མ͍ͪͯΔͷ͸࣮૷্ؒҧ͍ͬͯͨͱ͍͏͜ͱ͹͔Γͩͬͨɻ • ͖ͬͪΓςετ͍ͨ͠Ϛκͳํ͸1୆ήοτ͓ͯ͘͠ͱྑ͍͔΋ɻ
  19. ͦͷ3 ARM64୺຤Ͱଈࢮࣄ݅ @Android

  20. 64bit ͷ .so ͕͋Δͱ ABI ΋ 64bit ͳ͍ͱࢮ͵ • Android൛Ͱ͸Realmґଘ͍ͯ͠ΔωΠςΟϒϥΠϒϥϦΛ࢖͍ͬͯͨɻ

    • Xamarin಺Ͱ͸࢖͍ͬͯͳ͔ͬͨɻωΠςΟϒϥΠϒϥϦ͸ࢀর͍ͯ͠ΔͷΈɻ • ͢ΔͱGalaxy S6ͳͲͷARM64୺຤Ͱଈࢮ͢Δ • libmonodroid.so͕ͳ͍ͱग़ͨɻΞϓϦࣗମ͸ABI͍࣋ͬͯͳ͍͕ɺ
 Realm ͷωΠςΟϒϥΠϒϥϦͷ .so ͕ల։͞Εͨ͜ͱͰඞཁʹͳͬͯ͠·ͬͨɻ • ΞϓϦଆ΋64bit ABI Λαϙʔτͤ͞Δ͜ͱͰղܾɻ
  21. ͦͷ4 ऴྃͨ͠͸ͣͷը໘ͷը૾͕ ࢒ͬͯͯϝϞϦෆ଍ࣄ݅

  22. ͋ͪͪ͜Ͱىͬͨ͜໰୊ • ը૾͕ϝϞϦ্ʹ࢒ͬͯϦʔΫ / OOM • ಛʹ Android ͷ AnimationDrawable

    ͕͠Ϳͱ͔ͬͨ
  23. ίʔυͷதͰ࡞ͬͨΦϒδΣΫτ͸ඞͣղ์ʂ • ϑΟʔϧυʹࢀরΛ࣋ͬͨ
 ΦϒδΣΫτ͸
 ඞͣ Dispose/ࢀর֎͢͠Δ UIButton appendButton;
 
 public

    override void ViewDidLoad ()
 {
 base.ViewDidLoad ();
 appendButton = new UIButton(new CGRect(10,10, 200, 48));
 View.AddSubview(appendButton);
 }
 
 protected override void Dispose(bool disposing)
 {
 if (disposing)
 {
 if (appendButton != null)
 {
 appendButton.Dispose();
 appendButton = null;
 }
 }
 base.Dispose(disposing);
 }
 

  24. iOSͷ৔߹: Image,Layer ͷத਎΋ղ์͢Δ • ϓϩϑΝΠϥͰΈͨͱ͖ը૾͕࢒͍ͬͯͨ͜ͱ͕͋Δ • ͦ͏͍͏ͱ͖͸ ImageView ͷ
 Image,

    Layer.SubLayers ΋ۭʹͯ͠ɺ
 RemoveFromSuperview ͢Δͱྑ͍ɻ if (HogeImageView != null)
 {
 HogeImageView.Image = null;
 if (HogeImageView.Layer != null)
 {
 HogeImageView.Layer.Sublayers = null;
 } HogeImageView.RemoveFromSuperview();
 }
  25. Android: AnimationDrawable ͷ State ղ์ • AnimationDrawable Λ࢖ͬͨ৔߹ɺ
 தͷϑϨʔϜͷBitmap͕
 ղ์͞Εͳ͍ͷͰɺ


    ࣗ෼Ͱத਎ΛRecycleͯ͠
 SetState Ͱࢀর΋ղ์ͯ͠΍Δɻ void RecycleAnimationDrawable()
 {
 if (_drawableAnimation == null)
 {
 return; 
 }
 
 for (int i = 0; i < _drawableAnimation.NumberOfFrames; ++i)
 {
 var frame = _drawableAnimation.GetFrame(i);
 var bitmap = frame as BitmapDrawable;
 if ((bitmap != null) && !bitmap.IsRecycled)
 {
 bitmap.Recycle();
 bitmap.Dispose();
 }
 frame.Callback = null;
 }
 _drawableAnimation.Callback = null;
 _drawableAnimation.SetState(new int[] { });
 _drawableAnimation = null;
 }
  26. ͦͷ5 MvvmCross ͷ ListViewAdapter Viewੜ੒࣌ʹແବʹηοτ͕ಈ͘໰୊ @Android

  27. MvxListView ͷ MvxAdapter • MvxListView ༻ʹόΠϯσΟϯάՄೳͳ ViewItem Λఏڙ͢Δ Adapter •

    ͦͷ··࢖͏͜ͱ΋ɺΧελϜͯ͠࢖͏͜ͱ΋Ͱ͖Δɻ • CreateBindableView ΛΦʔόʔϥΠυ͢Δɻ • ͳ͔ͥ CreateBindableView ͷੜ੒࣌ʹΫϥογϡͯ͠͠·͏͜ͱ͕͋ͬͨɻ • ߲໨ View ͷ MvxImageView ͷதͰ SetImageDrawable(null) ͕ಈ͍͍ͯͨɻ
  28. CreateBindableView ൈ͚Δલʹ
 Binding ߋ৽͞ΕΔͷμϝ protected override IMvxListItemView CreateBindableView(object dataContext, int

    templateId)
 {
 var itemView = base.CreateBindableView(dataContext, templateId);
 var view = itemView as View;
 if (view != null)
 {
 var imageView = view.FindViewById<MvxImageView>(Resource.Id.timeline_image);
 imageView.ErrorImageResourceId = Resource.Drawable.img_live_object_loadfail;
 }
 return itemView;
 } %BUB$POUFYUͷ४උ͕ऴΘͬͯͳ͍λΠϛϯάͰݺ͹ΕΔ ˠը૾͕OVMM͕ೖͬͯ͘ΔՄೳੑ͕͋Δ
  29. DataContext ͸ॳظԽऴΘ͔ͬͯΒܨ͙ protected override IMvxListItemView CreateBindableView(object dataContext, int templateId)
 {


    var itemView = base.CreateBindableView(null, templateId);
 var view = itemView as View;
 if (view != null)
 {
 var imageView = view.FindViewById<MvxImageView>(Resource.Id.timeline_image);
 imageView.ErrorImageResourceId = Resource.Drawable.img_live_object_loadfail;
 }
 itemView.DataContext = dataContext;
 return itemView;
 }
 

  30. ͦͷ6 iOS 8 Ͱ୺຤ىಈޙҰൃ໨ͷ
 γϟολʔԻ͕໐Βͳ͍໰୊

  31. iOS 8 ͷγϟολʔ໐Βͳ͍όά • ೔ຊࠃ಺޲͚ͷ iPhone Ͱ͸αΠϨϯτϞʔυʹ͍ͯͯ͠΋
 γϟολʔԻ͕ͳΔ • ͔͠͠ɺiOS

    8 Ͱ͸ OS ىಈޙ 1 ճ໨ͷγϟολʔԻ͕໐Βͳ͍ɻ • Α͘஌ΒΕͨ iOS ࣗମͷόά
  32. iOS 8 ͷॳճͷΈɺ ڧ੍తʹγϟολʔԻΛ໐Β͢ (΍Βͳ͍ํ͕ྑ͍) • iOS ૊ΈࠐΈͷޮՌԻΛ໐Β͢ AudioToolBox.SystemSound •

    1108 ൪Λࢦఆ͢ΔͱɺΧϝϥͱಉ͡৚݅Ͱγϟολʔ͕໐Δ • iOS 8 ͷ൑ఆ͸ UIDevice.CurrentDevice.CheckSystemVersion ͰՄೳɻ • ౾஌ࣝɿ͜ͷϝιου͸ Xamarin ಠ֦ࣗு

  33. iOS 8 ͷॳճͷΈɺ ڧ੍తʹγϟολʔԻΛ໐Β͢ (΍Βͳ͍ํ͕ྑ͍) needDummyShutterSound = UIDevice.CurrentDevice.CheckSystemVersion(8, 0) 


    && !UIDevice.CurrentDevice.CheckSystemVersion(9, 0)
 && !dummyShutterSoundPlayed;
 : : if (needDummyShutterSound) 
 {
 needDummyShutterSound = false;
 dummyShutterSoundPlayed = true;
 var sound = new AudioToolbox.SystemSound(1108);
 sound.PlaySystemSound();
 } J04Ҏ্ɺJ04Ҏ্Ͱͳ͍ ͔ͭ·ͩ໐Βͯ͠ͳ͍ TUBUJDϑΟʔϧυ ൪ͷγεςϜα΢ϯυΛ໐Β͢
  34. ·ͱΊ

  35. ओͳ͸·ΓϙΠϯτճආํ๏ • HTTP௨৴पΓ͸ 
 ModernHttpClient (΋͘͠͸NSUrlSessionHandler/AndroidSessionHandler)Λ࢖͏ɻ
 iOS 8 ҎԼ͸ CFNetworkHandler

    Λ࢖ͬͨ΄͏͕Αͦ͞͏ɻ • ࢀরͨ͠ωΠςΟϒΦϒδΣΫτ͸͖ͪΜͱղ์͢Δɻ
 ಛʹը૾पΓ͸ղ์ʹؾΛ͚ͭΔɻ • Galaxyɺઈର͍ͭ͜͸Կ͔͋Δɻ1 ୆͋Δͱσόοάʹศརɻ
 Xamarin Test Cloud ʹ΋͍ͬͺ͍͋Γͦ͏͔ͩΒ׆༻͠Α͏ɻ
  36. ͍͞͝ʹ