【问题标题】:Xamarin forms PushAsync opens a blank pageXamarin 表单 PushAsync 打开一个空白页
【发布时间】:2017-06-12 15:51:56
【问题描述】:

我目前正在做一个项目,我在设备上收到推送通知,当点击通知时,它应该会打开一个特定页面。

我在 Android 5.1 上尝试过,但是当我点击通知时,它首先打开页面,然后立即打开一个空白页面,没有任何导航栏,我不明白为什么......

这是我的代码:

当我在 android 上收到消息时,我执行以下操作:

Intent intent = new Intent(this, typeof(MainActivity));
intent.PutExtra("key", "message");
PendingIntent pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);

Notification notif = new Notification.Builder(this)
                        .SetSmallIcon(Resource.Drawable.icon)
                        .SetContentTitle("Alert")
                        .SetContentText("alert message")
                        .SetAutoCancel(true)
                        .SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate)
                        .SetContentIntent(pendingIntent)
                        .SetPriority((int)NotificationPriority.High)
                        .Build();

NotificationManager notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(0, notif);

录制完成后,它会打开 MainActivity,它执行以下操作:

protected override void OnCreate(Bundle bundle)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;

    base.OnCreate(bundle);
    global::Xamarin.Forms.Forms.Init(this, bundle);
    if (app == null)
       app = new App();
    LoadApplication(app);

    // If the user tapped a notification
    if (Intent.Extras != null)
    {
        Data data = JsonConvert.DeserializeObject<Data>(Intent.Extras.GetString("key"));
        MessagingCenter.Send<Data>(data, "Show data");
    }
}

最后我有一个 DataPage(设置为应用程序的 MainPage,在 NavigationPage 内):

public DataPage()
{
    MessagingCenter.Subscribe<Data>(this, "Show data", (sender) =>
    {
        await Navigation.PushAsync(new DataDetail(sender));
    });
}

我真的不明白为什么这不能正常工作...... 特别是如果我这样做了

await Xamarin.Forms.Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(new DataPage(data)));

并在 DataPage 中创建第二个构造函数:

DataPage(Data data)
{
    await Navigation.PushAsync(new DataDetail(data));
}

它工作正常。 (但我不喜欢这个,看起来很……不好看)

【问题讨论】:

    标签: android xamarin xamarin.forms navigation


    【解决方案1】:

    我几乎无法理解你的DataDataDetailDataPageMainPage 之间的联系。

    在我这边,我认为Data 就像一个基于你的代码Data data = JsonConvert.DeserializeObject&lt;Data&gt;(Intent.Extras.GetString("key")); 的数据模型,但是在这个类中你编写了await Navigation.PushAsync(new DataDetail(data));,这个Navigation 是从哪里来的?

    没关系,我猜您有一个由NavigationPage 包裹的MainPage,并且您希望在单击通知时将其导航到您的DataPage。如果是这样,那么您的 Notification 部分没有问题。

    要显示DetailPage 中的数据,您可以创建一个带参数的构造函数,例如:

    public partial class DataPage : ContentPage
    {
        public DataPage()
        {
            InitializeComponent();
        }
    
        public DataPage(int count)
        {
            InitializeComponent();
            //set the data to the UI
            label.Text = "This is Count: " + count;
        }
    }
    

    您可以在MainPage 中为Navigation 创建单个实例,那么它是否可以在Data 类中使用:

    public static INavigation Navi;
    
    public MainPage()
    {
        InitializeComponent();
        Navi = this.Navigation;
    }
    

    那么我的Data 类就这么简单:

    public class Data
    {
        public Data()
        {
            MessagingCenter.Subscribe<Data>(this, "show data", (sender) =>
            {
                MainPage.Navi.PushAsync(new DataPage(this.Count));
            });
        }
    
        public int Count { get; set; }
    }
    

    终于在MainActivity:

    protected override void OnCreate(Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
    
        base.OnCreate(bundle);
    
        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());
    
        if (Intent.Extras != null)
        {
            int count = Intent.Extras.GetInt("count", -1);
            var data = new Data() { Count = count };
            MessagingCenter.Send<Data>(data, "show data");
        }
    }
    

    您可以根据需要修改Data 类。下面是我demo的渲染图:

    更新:

    根据我们的讨论,您的消息直接发送到DataPage,然后在PCL 的App 类中,用NavigationPage 包装这个DataPageMainPage = new NavigationPage(new DataPage());

    MainAcitvity 中发送这样的消息:

    if (Intent.Extras != null)
    {
        int count = Intent.Extras.GetInt("count", -1);
        var data = new Data() { Count = count }; //fake data, change it to your data
    
        var navipage = App.Current.MainPage as NavigationPage;
        var datapage = navipage.CurrentPage as DataPage;
        MessagingCenter.Send<DataPage, Data>(datapage, "show data", data);
    }
    

    而在DataPage

    public DataPage()
    {
        InitializeComponent();
        MessagingCenter.Subscribe<DataPage, Data>(this, "show data", (sender, arg) =>
        {
            Navigation.PushAsync(new DataDetail(arg));
        });
    }
    

    当然我们需要在DataDetail中创建一个讲师,参数为:

    public DataDetail(Data data)
    {
        InitializeComponent();
    }
    

    【讨论】:

    • 哦抱歉打错字了... 订阅消息中心“显示数据”消息的类是DataPage,也就是项目的MainPage。我在构造函数中打错了,应该是 public DataPage() { MessagingCenter.Subscribe(...);由于我的 DataPage 是 MainPage,因此包裹在 NavigationPage 中,例如 public App() { ... MainPage = new NavigationPage(new DataPage); .... } 看起来就像你在那里展示的那样,但它不能正常工作
    • 所以要明确一点:我的 MainPage 是 DataPage,它被包裹在 NavigationPage 中,并显示一个 ListView 绑定到数据列表(但它似乎与问题无关)。然后DataDetail是一个详细显示特定数据的页面,正如您所说的模型类。因此,DataPage() 中的 await Navigation 对我来说似乎是合法的。
    • @Simon,是的,但是您的消息中心将消息发送到 Data 类,在该类中,应该没有 Navigation 属性。这就是我在MainPage 中使用Navigation 的单个实例的原因。所以你的要求是从通知中获取数据并显示在你的DataPage中,你的数据页面是NavigationPage的根页面,对吗? DataDetail 在这里无关紧要?
    • 不完全是。 DataPage 确实是 Navigation 的根页面。当我点击通知并通过MessagingCenter发送消息时,接收它的是DataPage(我用调试器检查过,消息被有效接收)。收到消息 DataPage 后,我希望我的 DataPage 打开一个新的 DataDetail 页面,显示数据的详细信息。所以我要打开的 DataDetail 没有正确显示。
    • @Simon,好的,最后一个问题,你的代码MessagingCenter.Send&lt;Data&gt;(data, "Show data"); 中的Data 是什么?应该是一堂课吧?我看到你向Data 发送数据并在Data 的构造函数中订阅消息。这里的发送者也是Data类型的数据。
    【解决方案2】:

    所以我终于解决了这个问题。 似乎是因为我在 MainActivity 中做了一个静态 App 变量,以便只创建一次。

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        static App app;
    
        protected override void OnCreate(Bundle bundle)
        {
            ...
            if(app == null)
                app = new App();
            ...
         }
    }
    

    我这样做是因为否则应用实例的 Current.Properties 会被重置。

    现在我改变了它,我不再有这个问题: 我调用 Current.SavePropertiesAsync() 来保存 Current.Properties,因此我可以在 MainActivity 中删除 App 的静态实例。它解决了空白页问题。

    但这又带来了另一个问题。当我点击通知时,它第一次正常工作,但之后它多次打开请求的页面(第二个通知点击打开了 2 个页面,第三个打开了 3 个页面,...)。我不明白为什么会这样,但它似乎是由 MessagingCenter 引起的。所以我删除了 MessagingCenter 部分,并在 MainActivity 中简单地执行了此操作:

    if (Intent.Extras != null)
    {
         Data data = JsonConvert.DeserializeObject<Data>(Intent.Extras.GetString("key"));
         DataPage currentPage = (DataPage)((NavigationPage)App.Current.MainPage).CurrentPage;
         currentPage.OpenDataDetails(data);
    }
    

    在DataPage中我有这个功能

    public async void OpenDataDetails(Data data)
    {
        await Navigation.PushAsync(new DataDetail(data));
    }
    

    这确实按预期工作,所以现在我很高兴。

    但是,我仍然不明白为什么当我在 MainActivity 中有一个静态 App 实例时它会打开一个空白页面,也不明白为什么它会使用 MessagingCenter 打开多个页面...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      • 2017-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多