記事一覧

Android7.0 NougatでListViewがクラッシュする不具合の対応方法 | Xamarin.Forms


今回は Android7.0 Nougat (SDKバージョン24以降)においてXamarin.FormsのListViewをスクロールするとクラッシュする事が分かりました。
そこで調べてみると暫定ですが対応方法がわかりましたので、ご紹介いたします。

尚、エラー内容は
An Unhandled Exception
または
java.lang.NullPointerException:





前提条件
・Windows10 Pro 64Bit
・Visual Studio 2015 Community Update3
・Xamarin 4.3.0.795 (NuGet Xamarin.Forms 2.3.4.247)



1.原因

Android7.0 Nougat において ListViewCachingStrategy.RecycleElementを適用したListViewを使用するとエラーが発生するようです。
※RecycleElementについては以前の記事「LisViewのパフォーマンス向上方法」にてご紹介しております。
根本原因としては最新のNuGetパッケージのXamarin.Forms 2.3.4.247に起因するようですが、現状、新しいバージョンが出ていません。

Xamarin.Forms 2.3.5.233-pre1 にて対応がされているとの情報を元にパッケージマネージャからインストールして試してみましたが、私の環境では同じようにエラーとなりました。
Xamarin.Forms 2.3.5.256-pre6でも変わらずでした。



2.対応方法

現状のXamarin.FormsではListViewでRecycleElementを使用すると発生するようなので、Android7以降の場合はRetainElementにするというバージョン分岐(暫定処置)で対応します。
しかしながら、ListViewCachingStrategyは基底クラスのコンストラクタ内でのみの適用となっていますので、CSのみで記述する場合は簡単ですが、XAMLの場合、少し変わったコーディング方法にて対応します。

(1)CSのみで配置している場合
この場合は簡単です。ListViewのインスタンスを作成する際の引数にAndroidバージョン毎に切り替えたListViewCachingStrategy変数を渡すだけです。

TestPage.cs
public TestPage()
{
    // Android7対策の暫定処置 Xamarin.Forms 2.3.4.247以降で改善される予定?
    ListViewCachingStrategy strategy = ListViewCachingStrategy.RecycleElement;
    if (Device.RuntimePlatform == Device.Android &&
        DependencyService.Get<IDeviceService>().IsUpperVersion(24, 0) == true)  //Android7 Nougat 24-25
    {
        strategy = ListViewCachingStrategy.RetainElement;
    }
    ListView listView1 = new ListView(strategy);
}


(2)XAMLに配置してある場合
ListViewを継承したBaseListViewクラスを作成し、BaseListViewクラスをXAMLに記述します。(XAML上の記載方法については以前の記事「ListView のパフォーマンス向上方法」をご参考ください。

BaseListView.cs
using Xamarin.Forms;
public class BaseListView: ListView
{
    public ListViewCachingStrategy CachingStrategy { get; }

    public BaseListView(): base()
    {
        this.Initialize();
    }

    public BaseListView(ListViewCachingStrategy strategy) : base(BaseListView.GetStrategy(ref strategy))
    {
        this.CachingStrategy = strategy;
        this.Initialize();
    }

    /// <summary>
    /// Android7.0対策の暫定処置 Xamarin.Forms 2.3.5以降で改善される予定?
    /// </summary>
    /// <param name="strategy">ListViewCachingStrategy</param>
    /// <returns>ListViewCachingStrategy</returns>
    private static ListViewCachingStrategy GetStrategy(ref ListViewCachingStrategy strategy)
    {           
        if (Device.RuntimePlatform == Device.Android &&
            DependencyService.Get<IDeviceService>().IsUpperVersion(24, 0) == true)  //Android7 Nougat 24-25
        {
            strategy = ListViewCachingStrategy.RetainElement;
        }
        return strategy;
    }

    private void Initialize()
    {
        //コンストラクタ共通の初期化処理
    }
}

※DependencyServiceで使用しているIDeviceServiceクラスについては以前の記事「デバイス情報を取得する方法」にてご紹介しております。


2017/09/28追記
Xamarin.Forms 2.4.0.280にて修正が確認されています。しかしながらXF2.4.0.280は仕様変更が多く、次の記事で対応方法と追加機能についてご説明しておりますので、ご参考ください。






最後までお読みいただきありがとうございます。
当ブログの内容をまとめた Xamarin逆引きメニュー は以下のURLからご覧になれます。
http://itblogdsi.blog.fc2.com/blog-entry-81.html


関連記事

コメント

コメントの投稿

カテゴリ別記事一覧

広告

プロフィール

石河 純


著者名 :石河 純
自己紹介:素人上がりのIT技術者。趣味は卓球・車・ボウリング

IT関連の知識はざっくりとこんな感じです。
【OS関連】
WindowsServer: 2012/2008R2/2003/2000/NT4
Windows: 10/8/7/XP/2000/me/NT4/98
Linux: CentOS RedHatLinux9
Mac: macOS Sierra 10.12 / OSX Lion 10.7.5 / OSX Snow Leopard 10.6.8
【言語・データベース】
VB.net ASP.NET C#.net Java VBA
Xamarin.Forms
Oracle10g SQLServer2008R2 SQLAnywhere8/11/16
ActiveReport CrystalReport ReportNet(IBM)
【ネットワーク関連】
CCNP シスコ技術者認定
Cisco Catalyst シリーズ
Yamaha RTXシリーズ
FireWall関連
【WEB関連】
SEO SEM CSS IIS6/7 apache2

休みの日は卓球をやっています。
現在、卓球用品通販ショップは休業中です。