AndroidLayoutInflater的用法详解
相信我们在开发过程中肯定接触过LayoutInflater,比如ListView的适配器里的getView方法里通过LayoutInflater.from(Context).inflater来加载xml布局,在Fragment里的onCreateView里面也是一样,加载布局一共三种方法。 1,在Activity里面调用getLayoutInflater() 2, 通过LayoutInflater.from(context).inflater() 3, context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) 以上的三种方式从实现上都是一样的,Activity里面的getLayoutInflater()实际上调用的是PhoneWindow的实现,而PhoneWindow里源码的处理是LayoutInflater.from(context).inflater(),往下查找最终调用context.getSystemService。 context.getSystemService是Android里一个比较重要的api,是Activity的一个方法,根据传入的Name来取得对应的Object,然后转换成相应的服务对象。以下是系统相应的服务。 传入的Name返回的对象说明 WINDOW_SERVICE WindowManager 管理打开的窗口程序 LAYOUT_INFLATER_SERVICE LayoutInflater 取得xml里定义的view ACTIVITY_SERVICE ActivityManager 管理应用程序的系统状态 POWER_SERVICE PowerManger 电源的服务 ALARM_SERVICE AlarmManager 闹钟的服务 NOTIFICATION_SERVICE NotificationManager 状态栏的服务 KEYGUARD_SERVICE KeyguardManager 键盘锁的服务 LOCATION_SERVICE LocationManager 位置的服务,如GPS SEARCH_SERVICE SearchManager 搜索的服务 VEBRATOR_SERVICE Vebrator 手机震动的服务 CONNECTIVITY_SERVICE Connectivity 网络连接的服务 WIFI_SERVICE WifiManager Wi-Fi服务 TELEPHONY_SERVICE TeleponyManager 电话服务
但是LayoutInflater.from(context).inflater()的方法这么多,那它们到底是什么样的用法呢?
/** 341 * Inflate a new view hierarchy from the specified xml resource. Throws 342 * {@link InflateException} if there is an error. 343 * 344 * @param resource ID for an XML layout resource to load (e.g., 345 * <code>R.layout.main_page</code>) 346 * @param root Optional view to be the parent of the generated hierarchy. 347 * @return The root View of the inflated hierarchy. If root was supplied, 348 * this is the root View; otherwise it is the root of the inflated 349 * XML file. 350 */ 351 public View inflate(int resource, ViewGroup root) { 352 return inflate(resource, root, root != null); 353 } 354 355 /** 356 * Inflate a new view hierarchy from the specified xml node. Throws 357 * {@link InflateException} if there is an error. * 358 * <p> 359 * <em><strong>Important</strong></em> For performance 360 * reasons, view inflation relies heavily on pre-processing of XML files 361 * that is done at build time. Therefore, it is not currently possible to 362 * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. 363 * 364 * @param parser XML dom node containing the description of the view 365 * hierarchy. 366 * @param root Optional view to be the parent of the generated hierarchy. 367 * @return The root View of the inflated hierarchy. If root was supplied, 368 * this is the root View; otherwise it is the root of the inflated 369 * XML file. 370 */ 371 public View inflate(XmlPullParser parser, ViewGroup root) { 372 return inflate(parser, root, root != null); 373 } 374 375 /** 376 * Inflate a new view hierarchy from the specified xml resource. Throws 377 * {@link InflateException} if there is an error. 378 * 379 * @param resource ID for an XML layout resource to load (e.g., 380 * <code>R.layout.main_page</code>) 381 * @param root Optional view to be the parent of the generated hierarchy (if 382 * <em>attachToRoot</em> is true), or else simply an object that 383 * provides a set of LayoutParams values for root of the returned 384 * hierarchy (if <em>attachToRoot</em> is false.) 385 * @param attachToRoot Whether the inflated hierarchy should be attached to 386 * the root parameter? If false, root is only used to create the 387 * correct subclass of LayoutParams for the root view in the XML. 388 * @return The root View of the inflated hierarchy. If root was supplied and 389 * attachToRoot is true, this is root; otherwise it is the root of 390 * the inflated XML file. 391 */ 392 public View inflate(int resource, ViewGroup root, boolean attachToRoot) { 393 if (DEBUG) System.out.println("INFLATING from resource: " + resource); 394 XmlResourceParser parser = getContext().getResources().getLayout(resource); 395 try { 396 return inflate(parser, root, attachToRoot); 397 } finally { 398 parser.close(); 399 } 400 }
上面的方法非常清晰,直接看下inflate(parser, root, attachToRoot);
/** 403 * Inflate a new view hierarchy from the specified XML node. Throws 404 * {@link InflateException} if there is an error. 405 * <p> 406 * <em><strong>Important</strong></em> For performance 407 * reasons, view inflation relies heavily on pre-processing of XML files 408 * that is done at build time. Therefore, it is not currently possible to 409 * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. 410 * 411 * @param parser XML dom node containing the description of the view 412 * hierarchy. 413 * @param root Optional view to be the parent of the generated hierarchy (if 414 * <em>attachToRoot</em> is true), or else simply an object that 415 * provides a set of LayoutParams values for root of the returned 416 * hierarchy (if <em>attachToRoot</em> is false.) 417 * @param attachToRoot Whether the inflated hierarchy should be attached to 418 * the root parameter? If false, root is only used to create the 419 * correct subclass of LayoutParams for the root view in the XML. 420 * @return The root View of the inflated hierarchy. If root was supplied and 421 * attachToRoot is true, this is root; otherwise it is the root of 422 * the inflated XML file. 423 */ 424 public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { 425 synchronized (mConstructorArgs) { 426 final AttributeSet attrs = Xml.asAttributeSet(parser); 427 Context lastContext = (Context)mConstructorArgs[0]; 428 mConstructorArgs[0] = mContext; 429 View result = root; 430 431 try { 432 // Look for the root node. 433 int type; 434 while ((type = parser.next()) != XmlPullParser.START_TAG && 435 type != XmlPullParser.END_DOCUMENT) { 436 // Empty 437 } 438 439 if (type != XmlPullParser.START_TAG) { 440 throw new InflateException(parser.getPositionDescription() 441 + ": No start tag found!"); 442 } 443 444 final String name = parser.getName(); 445 446 if (DEBUG) { 447 System.out.println("**************************"); 448 System.out.println("Creating root view: " 449 + name); 450 System.out.println("**************************"); 451 } 452 453 if (TAG_MERGE.equals(name)) { 454 if (root == null || !attachToRoot) { 455 throw new InflateException("<merge /> can be used only with a valid " 456 + "ViewGroup root and attachToRoot=true"); 457 } 458 459 rInflate(parser, root, attrs, false); 460 } else { 461 // Temp is the root view that was found in the xml 462 View temp; 463 if (TAG_1995.equals(name)) { 464 temp = new BlinkLayout(mContext, attrs); 465 } else { 466 temp = createViewFromTag(root, name, attrs); 467 } 468 469 ViewGroup.LayoutParams params = null; 470 // 当父层不为空时 471 if (root != null) { 472 if (DEBUG) { 473 System.out.println("Creating params from root: " + 474 root); 475 } 476 // Create layout params that match root, if supplied // 获取父层的参数并赋值 477 params = root.generateLayoutParams(attrs); // 子布局不贴上也会被设置LayoutParams 478 if (!attachToRoot) { 479 // Set the layout params for temp if we are not 480 // attaching. (If we are, we use addView, below) 481 temp.setLayoutParams(params); 482 } 483 } 484 485 if (DEBUG) { 486 System.out.println("-----> start inflating children"); 487 } 488 // Inflate all children under temp 489 rInflate(parser, temp, attrs, true); 490 if (DEBUG) { 491 System.out.println("-----> done inflating children"); 492 } 493 494 // We are supposed to attach all the views we found (int temp) 495 // to root. Do that now. // 父布局不为空并且贴上会被add到父层 496 if (root != null && attachToRoot) { 497 root.addView(temp, params); 498 } 499 500 // Decide whether to return the root that was passed in or the 501 // top view found in xml. // 父布局为空或者没有贴上,result就是View本身 502 if (root == null || !attachToRoot) { 503 result = temp; 504 } 505 } 506 507 } catch (XmlPullParserException e) { 508 InflateException ex = new InflateException(e.getMessage()); 509 ex.initCause(e); 510 throw ex; 511 } catch (IOException e) { 512 InflateException ex = new InflateException( 513 parser.getPositionDescription() 514 + ": " + e.getMessage()); 515 ex.initCause(e); 516 throw ex; 517 } finally { 518 // Don't retain static reference on context. 519 mConstructorArgs[0] = lastContext; 520 mConstructorArgs[1] = null; 521 } 522 // 最后返回 result 523 return result; 524 } 525 }
由上源码我们可以得出: inflate(layout, null)返回的是View本身,且View本身所设置的布局参数无效,由父层和子View决定大小。 inflate(layout, null, false)同上一样,当父层为空,第三个值是否为真没有意义 inflate(layout, parent)子布局会被加入到父层并设置布局参数,具体大小由父层和子View决定 inflate(layout, parent, false)同上一样,区别就是false返回的是子View本身。 inflate(layout, parent, true)同第三个方法一样,返回父层View
优质内容筛选与推荐>>