fresco解析(2)之View

来源:互联网 发布:论坛网站排名数据库 编辑:程序博客网 时间:2024/06/05 17:40

如果让我来设计一个View的话,在Android中,属于自定义View的工作,常用的自定义View的方法都可以拿来用。但是,如果在View上必须draw一个Drawable,那自定义View的那一套就没有办法继续有用了。从Hierarchy来看,FB采用的好像是自定义Drawable的“捷径”——举个例子,画一个圆,既可以在正方形的画板上画一个圆,也可以在一个圆形的画板上,根据画板的“圆”这个特性,“描出”一个圆来。
如果对View这个“画板”自定义的话,那就可以定义一些属性,用来对Drawable进行设定。

所以说,光有Drawable还不行,它需要一个载体,也就是View。

1、“View”

还是通过继承关系,找到最顶端的类,看看作者背后的思考。
DraweeView就是用来展示Hierarchy的View。它继承自ImageView,但是不支持ImageView的setImageXxx, setScaleType等类似操作。FB选择让DraweeView继承它,主要是看中它类似padding的计算,后期可能会改成直接继承View。

public class DraweeView<DH extends DraweeHierarchy> extends ImageView {private final AspectRatioMeasure.Spec mMeasureSpec = new AspectRatioMeasure.Spec();  private float mAspectRatio = 0;  private DraweeHolder<DH> mDraweeHolder;  private boolean mInitialised = false;

DraweeView有一个很重要的函数如下,DraweeView必须设定DraweeController才可以正常显示Image。从这里就可以看出来,对ImageView设定图片来源,会定位到从mDraweeHolder来获取。

/** Sets the controller. */public void setController(@Nullable DraweeController draweeController) {  mDraweeHolder.setController(draweeController);  super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());}

比较重要的如 DH extends DraweeHierarchy和DraweeHolder。DraweeHolder比较简单,它之所以叫Holder,是因为它持有其他类型,“像是一个仓库”,装有不同类型的成员。

public class DraweeHolder<DH extends DraweeHierarchy> implements VisibilityCallback {private boolean mIsControllerAttached = false;  private boolean mIsHolderAttached = false;  private boolean mIsVisible = true;  private boolean mIsActivityStarted = true;  private DH mHierarchy;  private DraweeController mController = null;  private final ActivityListener mActivityListener;  private final DraweeEventTracker mEventTracker = new DraweeEventTracker();

看到这里,作者设计的思路也就出来了:继承自ImageView,并且有一个“Holder”,该“holder”持有MVC中的M,即Hierarchy,持有C,即DraweeController。对ImageView的将通过该Holder来处理。

2、GenericDraweeView

这个类简单,看它的构造函数。

public class GenericDraweeView extends DraweeView<GenericDraweeHierarchy> {public GenericDraweeView(Context context, GenericDraweeHierarchy hierarchy) {super(context);setHierarchy(hierarchy);}public GenericDraweeView(Context context) {super(context);inflateHierarchy(context, null);}public GenericDraweeView(Context context, AttributeSet attrs) {super(context, attrs);inflateHierarchy(context, attrs); // 从attrs里面提取属性}public GenericDraweeView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);inflateHierarchy(context, attrs);}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public GenericDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);inflateHierarchy(context, attrs);}

其中,从XML中提取属性的详细方法如下:

private void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {  Resources resources = context.getResources();// fading animation defaultsint fadeDuration = GenericDraweeHierarchyBuilder.DEFAULT_FADE_DURATION;// images & scale types defaultsint placeholderId = 0;ScalingUtils.ScaleType placeholderScaleType      = GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;  int retryImageId = 0;ScalingUtils.ScaleType retryImageScaleType =      GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;  int failureImageId = 0;ScalingUtils.ScaleType failureImageScaleType =      GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;  int progressBarId = 0;ScalingUtils.ScaleType progressBarScaleType =      GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;ScalingUtils.ScaleType actualImageScaleType =      GenericDraweeHierarchyBuilder.DEFAULT_ACTUAL_IMAGE_SCALE_TYPE;  int backgroundId = 0;  int overlayId = 0;  int pressedStateOverlayId = 0;// rounding defaultsboolean roundAsCircle = false;  int roundedCornerRadius = 0;  boolean roundTopLeft = true;  boolean roundTopRight = true;  boolean roundBottomRight = true;  boolean roundBottomLeft = true;  int roundWithOverlayColor = 0;  int roundingBorderWidth = 0;  int roundingBorderColor = 0;  int roundingBorderPadding = 0;  int progressBarAutoRotateInterval = 0;  if (attrs != null) {    TypedArray gdhAttrs = context.obtainStyledAttributes( // 备注:从XML里提取属性        attrs,R.styleable.GenericDraweeView);    try {final int indexCount = gdhAttrs.getIndexCount();      for (int i = 0; i < indexCount; i++) {final int idx = gdhAttrs.getIndex(i);// most popular ones firstif (idx == R.styleable.GenericDraweeView_actualImageScaleType) {// actual image scale typeactualImageScaleType = getScaleTypeFromXml(              gdhAttrs,R.styleable.GenericDraweeView_actualImageScaleType,actualImageScaleType);} else if (idx == R.styleable.GenericDraweeView_placeholderImage) {// placeholder imageplaceholderId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_placeholderImage,placeholderId);} else if (idx == R.styleable.GenericDraweeView_pressedStateOverlayImage) {// pressedState overlaypressedStateOverlayId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_pressedStateOverlayImage,pressedStateOverlayId);} else if (idx == R.styleable.GenericDraweeView_progressBarImage) {// progress bar imageprogressBarId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_progressBarImage,progressBarId);// the remaining ones without any particular order} else if (idx == R.styleable.GenericDraweeView_fadeDuration) {// fade durationfadeDuration = gdhAttrs.getInt(              R.styleable.GenericDraweeView_fadeDuration,fadeDuration);} else if (idx == R.styleable.GenericDraweeView_viewAspectRatio) {// aspect ratiosetAspectRatio(gdhAttrs.getFloat(              R.styleable.GenericDraweeView_viewAspectRatio,getAspectRatio()));} else if (idx == R.styleable.GenericDraweeView_placeholderImageScaleType) {// placeholder image scale typeplaceholderScaleType = getScaleTypeFromXml(              gdhAttrs,R.styleable.GenericDraweeView_placeholderImageScaleType,placeholderScaleType);} else if (idx == R.styleable.GenericDraweeView_retryImage) {// retry imageretryImageId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_retryImage,retryImageId);} else if (idx == R.styleable.GenericDraweeView_retryImageScaleType) {// retry image scale typeretryImageScaleType = getScaleTypeFromXml(              gdhAttrs,R.styleable.GenericDraweeView_retryImageScaleType,retryImageScaleType);} else if (idx == R.styleable.GenericDraweeView_failureImage) {// failure imagefailureImageId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_failureImage,failureImageId);} else if (idx == R.styleable.GenericDraweeView_failureImageScaleType) {// failure image scale typefailureImageScaleType = getScaleTypeFromXml(              gdhAttrs,R.styleable.GenericDraweeView_failureImageScaleType,failureImageScaleType);} else if (idx == R.styleable.GenericDraweeView_progressBarImageScaleType) {// progress bar image scale typeprogressBarScaleType = getScaleTypeFromXml(              gdhAttrs,R.styleable.GenericDraweeView_progressBarImageScaleType,progressBarScaleType);} else if (idx == R.styleable.GenericDraweeView_progressBarAutoRotateInterval) {// progress bar auto rotate intervalprogressBarAutoRotateInterval = gdhAttrs.getInteger(              R.styleable.GenericDraweeView_progressBarAutoRotateInterval,0);} else if (idx == R.styleable.GenericDraweeView_backgroundImage) {// backgroundbackgroundId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_backgroundImage,backgroundId);} else if (idx == R.styleable.GenericDraweeView_overlayImage) {// overlayoverlayId = gdhAttrs.getResourceId(              R.styleable.GenericDraweeView_overlayImage,overlayId);} else if (idx == R.styleable.GenericDraweeView_roundAsCircle) {// rounding parametersroundAsCircle = gdhAttrs.getBoolean(              R.styleable.GenericDraweeView_roundAsCircle,roundAsCircle);} else if (idx == R.styleable.GenericDraweeView_roundedCornerRadius) {          roundedCornerRadius = gdhAttrs.getDimensionPixelSize(              R.styleable.GenericDraweeView_roundedCornerRadius,roundedCornerRadius);} else if (idx == R.styleable.GenericDraweeView_roundTopLeft) {          roundTopLeft = gdhAttrs.getBoolean(              R.styleable.GenericDraweeView_roundTopLeft,roundTopLeft);} else if (idx == R.styleable.GenericDraweeView_roundTopRight) {          roundTopRight = gdhAttrs.getBoolean(              R.styleable.GenericDraweeView_roundTopRight,roundTopRight);} else if (idx == R.styleable.GenericDraweeView_roundBottomRight) {          roundBottomRight = gdhAttrs.getBoolean(              R.styleable.GenericDraweeView_roundBottomRight,roundBottomRight);} else if (idx == R.styleable.GenericDraweeView_roundBottomLeft) {          roundBottomLeft = gdhAttrs.getBoolean(              R.styleable.GenericDraweeView_roundBottomLeft,roundBottomLeft);} else if (idx == R.styleable.GenericDraweeView_roundWithOverlayColor) {          roundWithOverlayColor = gdhAttrs.getColor(              R.styleable.GenericDraweeView_roundWithOverlayColor,roundWithOverlayColor);} else if (idx == R.styleable.GenericDraweeView_roundingBorderWidth) {          roundingBorderWidth = gdhAttrs.getDimensionPixelSize(              R.styleable.GenericDraweeView_roundingBorderWidth,roundingBorderWidth);} else if (idx == R.styleable.GenericDraweeView_roundingBorderColor) {          roundingBorderColor = gdhAttrs.getColor(              R.styleable.GenericDraweeView_roundingBorderColor,roundingBorderColor);} else if (idx == R.styleable.GenericDraweeView_roundingBorderPadding) {          roundingBorderPadding = gdhAttrs.getDimensionPixelSize(              R.styleable.GenericDraweeView_roundingBorderPadding,roundingBorderPadding);}      }    } finally {      gdhAttrs.recycle();}  }/*备注:Builder...一下各个方法,主要对Builder的各个成员变量进行赋值从名字就可以看出来,该Builder是用来build出一个Hierarchy的。*/  GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources); // set fade durationbuilder.setFadeDuration(fadeDuration);// set images & scale typesif (placeholderId > 0) {    builder.setPlaceholderImage(resources.getDrawable(placeholderId), placeholderScaleType);}if (retryImageId > 0) {    builder.setRetryImage(resources.getDrawable(retryImageId), retryImageScaleType);}if (failureImageId > 0) {    builder.setFailureImage(resources.getDrawable(failureImageId), failureImageScaleType);}if (progressBarId > 0) {    Drawable progressBarDrawable = resources.getDrawable(progressBarId);    if (progressBarAutoRotateInterval > 0) {      progressBarDrawable =new AutoRotateDrawable(progressBarDrawable, progressBarAutoRotateInterval);}    builder.setProgressBarImage(progressBarDrawable, progressBarScaleType);}if (backgroundId > 0) {    builder.setBackground(resources.getDrawable(backgroundId));}if (overlayId > 0) {    builder.setOverlay(resources.getDrawable(overlayId));}if (pressedStateOverlayId > 0) {    builder.setPressedStateOverlay(getResources().getDrawable(pressedStateOverlayId));}  builder.setActualImageScaleType(actualImageScaleType);// set rounding parametersif (roundAsCircle || roundedCornerRadius > 0) {    RoundingParams roundingParams = new RoundingParams();roundingParams.setRoundAsCircle(roundAsCircle);    if (roundedCornerRadius > 0) {      roundingParams.setCornersRadii(          roundTopLeft ? roundedCornerRadius : 0,roundTopRight ? roundedCornerRadius : 0,roundBottomRight ? roundedCornerRadius : 0,roundBottomLeft ? roundedCornerRadius : 0);}if (roundWithOverlayColor != 0) {      roundingParams.setOverlayColor(roundWithOverlayColor);}if (roundingBorderColor != 0 && roundingBorderWidth > 0) {      roundingParams.setBorder(roundingBorderColor, roundingBorderWidth);}if (roundingBorderPadding != 0) {      roundingParams.setPadding(roundingBorderPadding);}    builder.setRoundingParams(roundingParams);}  setHierarchy(builder.build()); // build()出来所需要的“5”个Drawable,并赋值给 DraweeHolder}

上面build出来的Hierarchy会被赋值给Holder,这样Holder就持有Hierarchy的引用了。

  /** Sets the hierarchy. */  public void setHierarchy(DH hierarchy) {    mDraweeHolder.setHierarchy(hierarchy);    super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());  }

上面属性定义在attrs.xml中:

<?xml version="1.0" encoding="utf-8"?><resources>  <declare-styleable name="GenericDraweeView"><!-- Fade duration in milliseconds. --><attr name="fadeDuration" format="integer"/><!-- Images -    Scale types must match values in ScaleType.fromString (ScalingUtils.java).    For drawables that should not be scaled, such as those with the android:tileMode    attribute set, use the value 'none'. -->    <!-- Aspect ratio (width / height) of the view, not necessarily of the images. --><attr name="viewAspectRatio" format="float"/><!-- A drawable or color to be be used as a placeholder. --><attr name="placeholderImage" format="reference"/><!-- Scale type of the placeholder image. Ignored if placeholderImage is not specified. --><attr name="placeholderImageScaleType">      <enum name="none" value="-1" />      <enum name="fitXY" value="0" />      <enum name="fitStart" value="1" />      <enum name="fitCenter" value="2" />      <enum name="fitEnd" value="3" />      <enum name="center" value="4" />      <enum name="centerInside" value="5" />      <enum name="centerCrop" value="6" />      <enum name="focusCrop" value="7" />    </attr><!-- A drawable to be be used as a retry image. --><attr name="retryImage" format="reference"/><!-- Scale type of the retry image. Ignored if retryImage is not specified. --><attr name="retryImageScaleType">      <enum name="none" value="-1" />      <enum name="fitXY" value="0" />      <enum name="fitStart" value="1" />      <enum name="fitCenter" value="2" />      <enum name="fitEnd" value="3" />      <enum name="center" value="4" />      <enum name="centerInside" value="5" />      <enum name="centerCrop" value="6" />      <enum name="focusCrop" value="7" />    </attr><!-- A drawable to be be used as a failure image. --><attr name="failureImage" format="reference"/><!-- Scale type of the failure image. Ignored if failureImage is not specified. --><attr name="failureImageScaleType">      <enum name="none" value="-1" />      <enum name="fitXY" value="0" />      <enum name="fitStart" value="1" />      <enum name="fitCenter" value="2" />      <enum name="fitEnd" value="3" />      <enum name="center" value="4" />      <enum name="centerInside" value="5" />      <enum name="centerCrop" value="6" />      <enum name="focusCrop" value="7" />    </attr><!-- A drawable to be be used as a progress bar. --><attr name="progressBarImage" format="reference"/><!-- Scale type of the progress bar. Ignored if progressBarImage is not specified. --><attr name="progressBarImageScaleType">      <enum name="none" value="-1" />      <enum name="fitXY" value="0" />      <enum name="fitStart" value="1" />      <enum name="fitCenter" value="2" />      <enum name="fitEnd" value="3" />      <enum name="center" value="4" />      <enum name="centerInside" value="5" />      <enum name="centerCrop" value="6" />      <enum name="focusCrop" value="7" />    </attr><!-- Progress bar Auto Rotate interval in milliseconds --><attr name="progressBarAutoRotateInterval" format="integer"/><!-- Scale type of the actual image. --><attr name="actualImageScaleType">      <enum name="none" value="-1" />      <enum name="fitXY" value="0" />      <enum name="fitStart" value="1" />      <enum name="fitCenter" value="2" />      <enum name="fitEnd" value="3" />      <enum name="center" value="4" />      <enum name="centerInside" value="5" />      <enum name="centerCrop" value="6" />      <enum name="focusCrop" value="7" />    </attr><!-- A drawable or color to be used as a background. --><attr name="backgroundImage" format="reference"/><!-- A drawable or color to be used as an overlay. --><attr name="overlayImage" format="reference"/><!-- A drawable or color to be used as a pressed-state-overlay --><attr name="pressedStateOverlayImage" format="reference"/><!-- Rounding params -    Declares attributes for rounding shape, mode and border. -->    <!-- Round as circle. --><attr name="roundAsCircle" format="boolean"/><!-- Rounded corner radius. Ignored if roundAsCircle is used. --><attr name="roundedCornerRadius" format="dimension"/><!-- Round the top-left corner. Ignored if roundAsCircle is used. --><attr name="roundTopLeft" format="boolean"/><!-- Round the top-right corner. Ignored if roundAsCircle is used. --><attr name="roundTopRight" format="boolean"/><!-- Round the bottom-right corner. Ignored if roundAsCircle is used. --><attr name="roundBottomRight" format="boolean"/><!-- Round the bottom-left corner. Ignored if roundAsCircle is used. --><attr name="roundBottomLeft" format="boolean"/><!-- Round by overlying color. --><attr name="roundWithOverlayColor" format="color"/><!-- Rounding border width--><attr name="roundingBorderWidth" format="dimension"/><!-- Rounding border color --><attr name="roundingBorderColor" format="color"/><!-- Rounding border padding --><attr name="roundingBorderPadding" format="dimension" />  </declare-styleable></resources>

3、SimpleDraweeView

如注释所说,SimpleDraweeView接受一个 uri ,在内部会生成一个controller,并完成对controller的设定。如果说 Hierarchy是MVC中的M,SimpleDraweeView是MVC中的V,那 DraweeController就是MVC中的C。也就是说,DraweeController处于“中间”,负责协调两方的工作。
DraweeController的定义如下:既然它是连接两方SimpleDraweeView和Hierarchy,那它的功能无非就是“绑定”、“解绑”、“设定M(model)”、返回“model”、对V(View)的事件作出响应。

/** * Interface that represents a Drawee controller used by a DraweeView. * <p> The view forwards events to the controller. The controller controls * its hierarchy based on those events. */public interface DraweeController {/** Gets the hierarchy. */@Nullable  DraweeHierarchy getHierarchy(); // 备注:View传递events给controller,controller根据events调整Hierarchy,反过来又让View改变。这是典型的MVC的“循环”。
/** Sets a new hierarchy. */void setHierarchy(@Nullable DraweeHierarchy hierarchy);/**   * Called when the view containing the hierarchy is attached to a window   * (either temporarily or permanently).   */void onAttach();/**   * Called when the view containing the hierarchy is detached from a window   * (either temporarily or permanently).   */void onDetach();/**   * Called when the view containing the hierarchy receives a touch event.   * @return true if the event was handled by the controller, false otherwise   */boolean onTouchEvent(MotionEvent event);/**   * For an animated image, returns an Animatable that lets clients control the animation.   * @return animatable, or null if the image is not animated or not loaded yet   */Animatable getAnimatable();}

回到SimpleDraweeView。SimpleDraweeControllerBuilder仍然是一个Builder模式,用来build出一个DraweeController。

/** * This view takes a uri as input and internally builds and sets a controller. * * <p>This class must be statically initialized in order to be used. If you are using the Fresco * image pipeline, use {@link com.facebook.drawee.backends.pipeline.Fresco#initialize} to do this. */public class SimpleDraweeView extends GenericDraweeView {private static Supplier<? extends SimpleDraweeControllerBuilder> sDraweeControllerBuilderSupplier;/** Initializes {@link SimpleDraweeView} with supplier of Drawee controller builders. */public static void initialize(      Supplier<? extends SimpleDraweeControllerBuilder> draweeControllerBuilderSupplier) {    sDraweeControllerBuilderSupplier = draweeControllerBuilderSupplier;}/** Shuts {@link SimpleDraweeView} down. */public static void shutDown() {    sDraweeControllerBuilderSupplier = null;}private SimpleDraweeControllerBuilder mSimpleDraweeControllerBuilder;

SimpleDraweeView的构造函数,最终都需要调用init() : mSimpleDraweeControllerBuilder是从sDraweeControllerBuilderSupplier get到的,它的类型是Supplier<? extends SimpleDraweeControllerBuilder>。看来,Supplier对前者又是一个“包装”,而这个“包装”可以生成build出一个Controller。Supplier从字面上理解,它是一个“提供者”,那先考虑一下,它提供的是什么?

private void init() {if (isInEditMode()) {return;}  Preconditions.checkNotNull(      sDraweeControllerBuilderSupplier,"SimpleDraweeView was not initialized!");mSimpleDraweeControllerBuilder = sDraweeControllerBuilderSupplier.get();}

现在来说说fresco的基本使用:

a、初始化Fresco.initialize(this);
b、使用

//创建SimpleDraweeView对象simpleDraweeView = (SimpleDraweeView) findViewById(R.id.main_sdv);//创建将要下载的图片的URIUri imageUri = Uri.parse(uri);//开始下载simpleDraweeView.setImageURI(imageUri);public void setImageURI(Uri uri, @Nullable Object callerContext) {  DraweeController controller = mSimpleDraweeControllerBuilder// 备注:生成一个 controller      .setCallerContext(callerContext)      .setUri(uri)      .setOldController(getController())      .build();setController(controller); // 设置controller}/** Sets the controller. */public void setController(@Nullable DraweeController draweeController) {  mDraweeHolder.setController(draweeController);  super.setImageDrawable(mDraweeHolder.getTopLevelDrawable()); // 从controller里面提取Drawable}

controller是由SimpleDraweeControllerBuilder生成的,而SimpleDraweeControllerBuilder是由sDraweeControllerBuilderSupplier get 出来的。
由此可见:sDraweeControllerBuilderSupplier ,即Supplier会“提供” DraweeController的Builder。可见,Fresco.initialize(this);里面会生成一个Supplier,并且生成一个SimpleDraweeControllerBuilder。

4、总结:

“View”体系也不复杂。其通过XML提取属性,构造一个Controller(MVC中的C,持有M和V,并连同M和V),根据这些属性构造一个Hierarchy,进而生成各个Drawable。并通过Supplier来提供来源更多的Drawable。fresco更精彩的地方在于Supplier和Controller。在这个过程中的Builder也好,还是Holder也好,都是辅助MVC的。Builder模式比较灵活,能够隐藏build出来对象的细节。Holder作为一个“容器”式的存在,持有对其他对象的引用,把多个对象集中在一起管理,比较简洁和方便。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕妇7个月血糖高怎么办 空腹血糖6%2e7怎么办 血糖和尿酸都高怎么办 血糖高的孕妇便秘怎么办 血糖低怎么办吃什么好 孕检空腹血糖高怎么办 怀孕4个月血糖高怎么办 怀孕3个月血糖高怎么办 怀孕6个月血糖高怎么办 孕29周血糖高怎么办 餐后血糖偶尔高怎么办 歺后血糖9.8高怎么办 怀孕5个月血糖高怎么办 歺后2小时血糖高怎么办 怀孕餐后血糖高怎么办 老人餐后血糖高怎么办 血糖高尿糖不高怎么办 小孩鼻子不通气怎么办特效方法 婴儿20天不大便怎么办 新生儿8天没大便怎么办 新生儿2天没大便怎么办 新生儿4天没大便怎么办 2岁宝宝便秘严重怎么办 婴儿7天没有大便怎么办 新生儿6天没大便怎么办 大便带鲜血 不疼怎么办 宝宝发烧到39度怎么办 肛裂大便出鲜血怎么办 拉大便有血怎么办啊 长痔疮拉大便血怎么办 病人卧床太久不解大便怎么办 宝宝拉泡沫便便怎么办 孩子拉肚子怎么办呢有好办法吗 2岁宝宝大便带血怎么办 十个月宝宝肛裂怎么办 大便时拉出血怎么办啊 2岁宝宝大便干燥怎么办 5岁儿童大便干燥怎么办 九个月宝宝平血怎么办 6个月宝宝肛裂怎么办 3岁儿童大便干燥怎么办