Xamarin.Android WebView App性能问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xamarin.Android WebView App性能问题相关的知识,希望对你有一定的参考价值。
我正在开发一个Xamarin.android应用程序,该应用程序正在遭遇性能问题。
该应用包含以下内容:
- 启动画面延迟1秒。
- 主要活动包括视图寻呼机,标签式布局,9个片段,广告视图。
- 每个片段都包含Webview。
主要活动代码:
namespace XXXXX
{
[Activity(Label = "XXX", Theme = "@style/AppTheme", ScreenOrientation =
Android.Content.PM.ScreenOrientation.Portrait)]
public class MainActivity : AppCompatActivity
{
AdView adView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
Toolbar toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
var fragments = new Fragment[]
{
new homeFragment(),
new XXXFragment(),
new XXXFragment(),
new XXXFragment(),
new XXXFragment(),
new XXXFragment(),
new XXXFragment(),
new XXXFragment(),
newXXXFragment(),
};
var titles = CharSequence.ArrayFromStringArray(new[]
{
"XXX",
"XXX",
"XXX",
"XXX",
"XXX",
"XXX",
"XXX",
"XXX",
"XXX"
});
var viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
viewPager.OffscreenPageLimit = 1;
viewPager.Adapter = new TabsFragmentPagerAdapter(SupportFragmentManager, fragments, titles);
// Give the TabLayout the ViewPager
var tabLayout = FindViewById<TabLayout>(Resource.Id.sliding_tabs);
tabLayout.SetupWithViewPager(viewPager);
var isConnected = CrossConnectivity.Current.IsConnected;
if (isConnected)
{
Task.Run(() =>
{
// Log.Debug("TAG", "InstanceID token: " + FirebaseInstanceId.Instance.Token);dddd
var instanceid = FirebaseInstanceId.Instance;
instanceid.DeleteInstanceId();
Log.Debug("TAG", "{0} {1}", instanceid.Token, instanceid.GetToken(this.GetString(Resource.String.gcm_defaultSenderId), Firebase.Messaging.FirebaseMessaging.InstanceIdScope));
});
FirebaseMessaging.Instance.SubscribeToTopic("custom");
}
var iid = "#####";
Android.Gms.Ads.MobileAds.Initialize(ApplicationContext, iid);
adView = FindViewById<AdView>(Resource.Id.adView);
AdRequest adRequest = new AdRequest.Builder().Build();
adView.LoadAd(adRequest);
adView.BringToFront();
}
protected override void OnResume()
{
if (adView != null) adView.Resume();
base.OnResume();
}
protected override void OnPause()
{
if (adView != null) adView.Pause();
base.OnPause();
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.top_menus, menu);
return base.OnCreateOptionsMenu(menu);
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
Intent intent;
switch (item.ItemId)
{
case Resource.Id.nav_feedback:
intent = new Intent(this, typeof(Feedback));
StartActivity(intent);
return true;
case Resource.Id.nav_settings:
intent = new Intent(this, typeof(Settings));
StartActivity(intent);
return true;
default:
break;
}
return base.OnOptionsItemSelected(item);
}
}
}
每个片段包含:
namespace XXXXX
{
public class HomeFragment : Fragment
{
public ProgressBar progress;
public WebView mWebView;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate(Resource.Layout.HomeFragmentLayout, container, false);
mWebView = view.FindViewById<WebView>(Resource.Id.webView1);
progress = view.FindViewById<ProgressBar>(Resource.Id.progressBar);
progress.Visibility = ViewStates.Visible;
mWebView.Settings.DomStorageEnabled = true;
mWebView.Settings.javascriptEnabled = true;
mWebView.Settings.LoadWithOverviewMode = true;
mWebView.Settings.UseWideViewPort = true;
mWebView.Settings.SetSupportZoom(false);
mWebView.Settings.BuiltInZoomControls = false;
mWebView.Settings.SetEnableSmoothTransition(true);
mWebView.Settings.SetAppCacheEnabled(true);
mWebView.Settings.SetAppCacheMaxSize(1024 * 1024 * 8);
mWebView.Settings.SetAppCachePath(Context.CacheDir.ToString());
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
mWebView.SetLayerType(LayerType.Hardware, null);
else
mWebView.SetLayerType(LayerType.Software, null);
mWebView.LoadUrl("link");
mWebView.SetWebViewClient(new HybridWebViewClient(Context, this));
mWebView.SetWebChromeClient(new WebChromeClient());
if (CrossConnectivity.Current.IsConnected)
{
mWebView.Settings.CacheMode = CacheModes.Default;
mWebView.Reload();
}
else
{
mWebView.Settings.CacheMode = CacheModes.CacheElseNetwork;
}
return view;
}
public class HybridWebViewClient : WebViewClient
{
private Context context;
private HomeFragment homeFragment;
public HybridWebViewClient(Context context, HomeFragment homeFragment)
{
this.context = context;
this.homeFragment = homeFragment;
}
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
System.Diagnostics.Debug.WriteLine("ShouldOverrideUrlLoading:" + url);
if (url.StartsWith("whatsapp:") || url.StartsWith("tel:"))
{
Intent intent = new Intent(Intent.ActionView,
Android.Net.Uri.Parse(url));
context.StartActivity(intent);
return true;
}
else if (url.StartsWith("tohttp:"))
{
var DetailedNewsIntent = new Intent(context, typeof(DetailedNewsActivity));
DetailedNewsIntent.PutExtra("Url", url);
context.StartActivity(DetailedNewsIntent);
return true;
}
else
{
view.LoadUrl(url);
return true;
}
}
public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon)
{
base.OnPageStarted(view, url, favicon);
}
public override void OnPageFinished(WebView view, string url)
{
homeFragment.progress.Visibility = ViewStates.Gone;
base.OnPageFinished(view, url);
}
public override void OnReceivedError(WebView view, [GeneratedEnum] ClientError errorCode, string description, string failingUrl)
{
base.OnReceivedError(view, errorCode, description, failingUrl);
}
}
}
}
启动画面:
namespace XXXX
{
[Activity(Theme = "@style/MyTheme.Splash", NoHistory = true, MainLauncher =
true)]
public class SplashActivity : Activity
{
static readonly string TAG = "X:" + typeof(SplashActivity).Name;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Log.Debug(TAG, "SplashActivity.OnCreate");
// Create your application here
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() => {
Log.Debug(TAG, "Performing some startup work that takes a bit of time.");
Task.Delay(1000); // Simulate a bit of startup work.
Log.Debug(TAG, "Working in the background - important stuff.");
});
startupWork.ContinueWith(t => {
Log.Debug(TAG, "Work is finished - start Activity1.");
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
Finish();
}, TaskScheduler.FromCurrentSynchronizationContext());
startupWork.Start();
}
}
}
现在为了提高性能,我已尝试过以下但性能未受到预期的影响
- 最小启动延迟(静态应用程序需要花时间进行启动
- viewPager.OffscreenPageLimit = 1; (从1到9)
- Adview异步(需要同时)
该应用程序花费大部分时间进行启动活动
- 我想更快地启动应用程序。
- 想要在交换片段时保持页面加载。 (目前,页面在淹没时闪烁)
应用环境 -
- XA Marin.Android 8.0
- 适用于Xamarin 4.7的Visual Studio工具
- Visual Studio 15.4.3
- minSDK API - 14
- 有针对性的SDK API - 25
- 建筑 - armeabi-v7a
套餐 -
- Plugin.CurrentActivity
- Plugin.Share
- Xam.Plugin.Connectivity
- XA Marin.Android.support.design 25.4.0.2
- Xamarin.GooglePlayServices.Ads.Lite 42.1021.1
- Xamarin.Firebase.Messaging 42.1021.1
请任何人知道调整/提示/黑客提高性能请分享。 TIA !!
答案
FragmentStatePagerAdapter
如果有大量的页面,比如你的9页,你的TabsFragmentPagerAdapter
应该扩展FragmentStatePagerAdapter类。因为当片段对用户不可见时,片段可能被破坏,并且它允许寻呼机保持更少的内存,它将具有比FragmentPagerAdapter更好的性能。您可以通过链接比较它们。两者在使用上都相似。
UserVisibleHint
下面是UserVisibleHint
的一个简单的片段延迟加载,在你的片段可见之前你不需要加载数据:
public class Fragment1 : Fragment
{
bool isViewInit;
bool isDataLoad;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
var view= inflater.Inflate(Resource.Layout.YourFragment, container, false);
isViewInit = true;
return view;
}
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
if (UserVisibleHint) {
loadData();
}
}
public override bool UserVisibleHint {
get => base.UserVisibleHint;
set {
base.UserVisibleHint = value;
if (UserVisibleHint && isViewInit && !isDataLoad) {
loadData();
}
}
}
private void loadData()
{
//load your data here
isDataLoad = true;
}
}
以上是关于Xamarin.Android WebView App性能问题的主要内容,如果未能解决你的问题,请参考以下文章
在 Xamarin Android App 中使用 webview 上传文件
如果“target=_blank”,Xamarin Android WebView 不会触发导航
Xamarin.Form与Xamarin.Android或Xamarin.IOS的区别简述
Xamarin.Android 反复报 Please Download android_m2repository_rxx.zip 的解决办法