【问题标题】:How to improve fragment loading speed?如何提高片段加载速度?
【发布时间】:2014-12-03 14:56:30
【问题描述】:

性能增强:

之前我将ALL图像保存在drawable文件夹中,这可能是地图首次加载缓慢的原因,当在屏幕上绘制标记时,图像可能不适合屏幕大小。 现在我把图片保存在drawable-mdpidrawable-hdpi等等,应用比以前更流畅了。希望对你有帮助

原问题:

我在一个片段中创建了一个地图,源代码可以在下面找到。

地图片段在第一次加载时缓慢。如果我去任何其他片段并再次单击地图片段,它会快速加载并且不再有 slug。

谁能告诉我这里发生了什么?谢谢!

fragment_map.xml,id 是map

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.google.android.gms.maps.SupportMapFragment" />

MyMapFragment.java(包含onCreateView setUpMapIfNeeded

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    try {
        rootView = inflater.inflate(R.layout.fragment_map, container, false);
    } catch (InflateException e) {
    /* map is already there, just return view as it is */
        Log.e(TAG, "inflateException");
    }

    setUpMapIfNeeded();
     
    return rootView;
}


public void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the fragment_map.
    if (myMap == null) {
        // Try to obtain the fragment_map from the SupportMapFragment.
        myMap = ((SupportMapFragment) MainActivity.fragmentManager.findFragmentById(R.id.map)).getMap();
        // Check if we were successful in obtaining the fragment_map.
        if (myMap != null) {
            setUpMap();
        }
    }
}

【问题讨论】:

  • 你有没有想过这件事?
  • 我添加了一个小(脏)修复作为答案,因为这个问题仍然存在

标签: android android-maps-v2 android-maps


【解决方案1】:

我在我的应用程序中使用了一种非常老套但有效的方法,但效果很好。 应用程序启动后,我的 mapFragment 没有立即显示!否则这是没有意义的。

把它放在你的启动器活动的onCreate中:

    // Fixing Later Map loading Delay
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                MapView mv = new MapView(getApplicationContext());
                mv.onCreate(null);
                mv.onPause();
                mv.onDestroy();
            }catch (Exception ignored){

            }
        }
    }).start();

这将在后台线程(远离 ui)中创建一个地图视图,并使用它初始化所有 google play 服务和地图数据。

加载的数据大约额外增加了 5MB。

如果有人有一些改进的想法,请随时发表评论!


Java 8 版本:

// Fixing Later Map loading Delay
new Thread(() -> {
    try {
        MapView mv = new MapView(getApplicationContext());
        mv.onCreate(null);
        mv.onPause();
        mv.onDestroy();
    }catch (Exception ignored){}
}).start();

【讨论】:

  • 实际上,我很乐意为此赏金。是否可以为此开始赏金,还是“违反规则”?认真问..
  • 这在 Android 5.1 上运行良好,在运行 4.0.4 的设备上崩溃:RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
  • 尝试使用runOnUiThread()而不是new Thread().start()在UI线程上运行Runnable
  • 哈哈,如果你不忽略异常你会得到一个java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
  • FWIW 我打开了一个针对 Google 的错误:issuetracker.google.com/issues/80147879 如果您认为他们应该从问题的根本上解决这个问题,请随意给它加星标
【解决方案2】:

只是为了添加到@Xyaren 的答案,我需要它来为 SupportFragment 工作,这似乎需要一些额外的步骤。让您的活动实现 OnMapReadyCallback。

在您的 onCreate 中:

new Thread(() -> {
    try {
        SupportMapFragment mf = SupportMapFragment.newInstance();
        getSupportFragmentManager().beginTransaction()
                .add(R.id.dummy_map_view, mf)
                .commit();
        runOnUiThread(() -> mf.getMapAsync(SplashActivity.this));
    }catch (Exception ignored){
        Timber.w("Dummy map load exception: %s", ignored);
    }
}).start();

你必须实现这个:

@Override
public void onMapReady(GoogleMap googleMap) {
    // Do nothing because we only want to pre-load map.
    Timber.d("Map loaded: %s", googleMap);
}

在你的活动布局中:

<FrameLayout
    android:id="@+id/dummy_map_view"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:visibility="gone"/>

它需要完成所有步骤,包括Google Play服务下载地图数据的交易。

【讨论】:

    【解决方案3】:

    我也经常遇到这个问题...原来最大的罪魁祸首是在我的应用程序进程中附加了一个调试会话。当我断开调试器或拔下 USB 电缆时,我的应用程序中的地图运行得更快、更流畅。

    在这里查看我的相关帖子:First launch of Activity with Google Maps is very slow

    【讨论】:

    • or just unplugged the USB cable 这对我帮助很大
    【解决方案4】:

    [编辑]

    getMap()setUpMap() 方法可能非常慢。他们的处理应该在AsyncTask 中完成,以便onCreateView() 每次都能快速返回。

    更多信息:onCreateView() 在 UI 线程上调用,因此它所做的任何缓慢处理都会冻结 UI。您的 AsyncTask 应该在其 doInBackground() 方法中完成所有缓慢的处理,然后在其 onPostExecute() 方法中更新 UI。有关详细信息,请参阅AsyncTask JavaDoc

    【讨论】:

    • 感谢您的快速回复,当我注释掉setUpMap时仍然很慢
    • getMap() 可能很慢。因此,对getMap() 的调用也应该由AsyncTask 处理。我已经编辑了我的答案。
    • 我的片段中的getMap() 和由AsyncTask 处理的有什么区别?如果我把它放到 asynctask 中,我怎么知道 getMap() 除了 null 之外已经准备好了?
    • 我在我的回答中加入了更多信息。
    • 感谢您的帮助,我尝试了 asynctask,没有帮助
    【解决方案5】:

    你可以试试这个

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mapActivity);
        getSreenDimanstions();
        fragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
        
        map = fragment.getMap();    
    }
    

    这个类是从Activity扩展而来的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      • 1970-01-01
      • 2012-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      相关资源
      最近更新 更多