Jiliuke

激流客

  1. 访问开发文档搜索并点击Create a test-only Payflow Gateway account,继续点击Payflow Services开始创建账号,根据需要的类型选择支付处理公司,除了邮件其他随意填继续下一步到结束。完成后会有成功注册信息发送到邮箱。

  2. 根据邮件登录信息登录登录paypal payflow后台,

  • 点击
    Service Setting->Set Up->Payment Confirmation中,修改Show confirmation pagew为On my website,修改Return URL MethodPost。转到Security Options,修改Enable Secure TokenYes,保存;
  • 导航到Service Setting->Customize->Choose a layout and color,选择Layout C,然后保存发布(Save and Publish);
  • 导航到Account Administration->Manage Security->Transaction Settings,修改Allow reference transactionsYes,保存(Confirm);
  1. magento2后台配置paypal payflow后即可使用测试信用卡测试。

问题

magento-cloud新项目添加magento-cloud ssh-key:add后仍然无法pull代码,

处理

解决方法如下:

1.需要配置~/.ssh/config文件,例如:

gedit ~/.ssh/config,

拷贝以下到~/.ssh/config

1
2
3
4
Host git.us-3.magento.cloud
Hostname git.us-3.magento.cloud
User tajmoznp6wqkq
IdentityFile /home/dyl/.ssh/id_rsa.2

2.获取公钥写入到~/.ssh/known_hosts中,终端执行以下命令:

1
ssh-keyscan -H git.us-3.magento.cloud >> ~/.ssh/known_hosts

简介

很多情况下我们需要修改后台eav属性对应的模板文件。以下是通过修改模板文件让客户无法在后台修改multiple select,也就是disable multiple select。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--
Silk/AdvancedEstimatedShippingDate/etc/adminhtml/di.xml
-->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
<arguments>
<argument name="modifiers" xsi:type="array">
<item name="esd" xsi:type="array">
<item name="class" xsi:type="string">Silk\AdvancedEstimatedShippingDate\Ui\DataProvider\Product\Form\Modifier\esd</item>
<item name="sortOrder" xsi:type="number">10</item>
</item>
</argument>
</arguments>
</virtualType>
</config>

接下来修改modifyMeta

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//Silk\AdvancedEstimatedShippingDate\Ui\DataProvider\Product\Form\Modifier\esd
<?php
/**
* Created by PhpStorm.
* User: dyl
* Date: 18-4-17
* Time: 下午4:31
*/

namespace Silk\AdvancedEstimatedShippingDate\Ui\DataProvider\Product\Form\Modifier;
use Magento\Framework\Stdlib\ArrayManager;

class esd implements \Magento\Ui\DataProvider\Modifier\ModifierInterface
{
/**
* Container fieldset prefix
*/
const CONTAINER_PREFIX = 'container_';
/**
* @var ArrayManager
*/
protected $arrayManager;

/**
* esd constructor.
* @param ArrayManager $arrayManager
*/
public function __construct(ArrayManager $arrayManager)
{
$this->arrayManager = $arrayManager;
}

/**
* @param array $data
* @return array
*/
public function modifyData(array $data)
{
return $data;
}

/**
* @param array $meta
* @return array
*/
public function modifyMeta(array $meta)
{
$fieldCode = 'esd';
$elementPath = $this->arrayManager->findPath($fieldCode, $meta, null, 'children');
$containerPath = $this->arrayManager->findPath(static::CONTAINER_PREFIX . $fieldCode, $meta, null, 'children');
if (!$elementPath) {
return $meta;
}

$meta = $this->arrayManager->merge(
$containerPath,
$meta,
[
'arguments' => [
'data' => [
'config' => [
'formElement' => 'container',
'componentType' => 'container',
'breakLine' => false,
'label' => __('ESD'),
'required' => 0,
'sortOrder' => 320,
'scopeLabel' => __('[STORE VIEW]'),
],
],
],
'children' => [
$fieldCode => [
'arguments' => [
'data' => [
'config' => [
'dataType' => 'multiselect',
'formElement' => 'multiselect',
'elementTmpl' => 'Silk_AdvancedEstimatedShippingDate/ui/form/element/multiselect'
],
],
],
],
]
]
);
return $meta;
}
}

最后加上template文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!--
Silk/AdvancedEstimatedShippingDate/view/base/web/template/ui/form/element/multiselect.html
-->
<!--
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<select multiple class="admin__control-multiselect" data-bind="
attr: {
name: inputName,
id: uid,
size: size ? size : '6',
disabled: true,
'aria-describedby': noticeId,
placeholder: placeholder
},
hasFocus: focused,
optgroup: options,
selectedOptions: value,
optionsValue: 'value',
optionsText: 'label'"
/>

由于 Ubuntu 是基于 Debian 的 linux 操作系统,在默认的情况下,是没有超级用户(superuser, root)的,但有些系统操作必须有超级用户的权限才能进行,如手动释放内存等。 在其他 linux 操作系统(如 fedora)下,可以使用 su 切换到超级用户。 当输入 su 命令后,系统会要求输入 root 的密码。 可是,在 Ubuntu 下我们根本不知道 root 的密码是什么。 这样,在 Ubuntu 下切换到超级用户需要使用其他方法,主要有两种: 1) sudo -i sudo 是 su 的加强版,意思是 do something as the supervisor。不需要密码就可以得到 root 的权限。 但是它也有很多限制,比如,在默认的情况下,只能在 5 分钟之内使用 root 权限。 2)如果想一直使用 root 权限,还是要使用 su,还是要得到 root 密码的。 用 sudo passwd root 可以设置 root 的密码。 之后就可以自由使用 su 命令啦。

本篇文章是对PHP函数ip2long转换IP时数值太大产生负数的解决方法进行了详细的分析介绍,需要的朋友参考下 【造成原因】:Because PHP’s integer type is signed, and many IP addresses will result in negative integers. 【解决办法】:其官方手册中提到,可以“you need to use the “%u” formatter of sprintf() or printf() to get the string representation of the unsigned IP address” 即,printf( ‘%u’,ip2long(‘IP地址’ ) ); 或者将其先转换为二进制然后在转换为十进制,bindec(decbinip2long( ‘IP地址’ ) ) ); 【测试】

$strIp = '182.118.0.0';
echo ip2long($strIp); //此时输出的-1233780736
echo 'br/';
echo bindec( decbin( ip2long( $strIp ) ) ); // 输出3061186560,与MySQL函数输出一致~

【注】: number bindec ( string $binary_string ); //二进制转换为十进制 string decbin ( int $number ); //十进制转换为二进制

Indexer.php 添加同义词

添加同义词

通过带参数的选项 --add-synonym 来实现,参数值为单条或多条同义词记录,每条记录之间用冒号(:) 分隔原词和同义词,多条记录之间用逗号分割。您可以对同一个“原词”增加多个不同的“同义词”, 如果库内已存在完全一致的记录,则指令不起作用也不会报错。用法如下:

# 给 search 增加同义词 find
util/Indexer.php demo –add-synonym search:find

# 再给 search 增加另一个同义词 seek
util/Indexer.php demo –add-synonym search:seek

# 给 “搜索” 增加 “检索” “查找” 两个同义词
util/Indexer.php demo -add-synonym 搜索:检索,搜索:查找

# 给 “Hello world” 增加同义词 “你好”,参数含空格请用引号包围
util/Indexer.php demo –add-synonym “Hello world:你好”

删除同义词

删除同义词作法和添加同义词很相似,只不过采用选项 --del-synonym,同时参数中的同义词可以 省略表示删除该“原词”的所有同义词记录。用法如下:

# 删除 search 的全部同义词、同时删除 “搜索” 的同义词 “检索”
util/Indexer.php demo –del-synonym search,搜索:检索

invalidate()函数的主要作用是请求View树进行重绘,该函数可以由应用程序调用,或者由系统函数间接调用,例如setEnable(), setSelected(), setVisiblity()都会间接调用到invalidate()来请求View树重绘,更新View树的显示。 注:requestLayout()和requestFocus()函数也会引起视图重绘 下面我们通过源码来了解invalidate()函数的工作原理,首先我们来看View类中invalidate()的实现过程:

[java] view plaincopy

  1. /**
  2.      * Invalidate the whole view. If the view is visible,
  3.      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
  4.      * the future. This must be called from a UI thread. To call from a non-UI thread,
  5.      * call {@link #postInvalidate()}.
  6.      */
  7.     public void invalidate() {
  8.         invalidate(true);
  9.     }

invalidate()函数会转而调用invalidate(true),继续往下看:

[java] view plaincopy

  1. /**

  2.      * This is where the invalidate() work actually happens. A full invalidate()

  3.      * causes the drawing cache to be invalidated, but this function can be called with

  4.      * invalidateCache set to false to skip that invalidation step for cases that do not

  5.      * need it (for example, a component that remains at the same dimensions with the same

  6.      * content).

  7.      *

  8.      * @param invalidateCache Whether the drawing cache for this view should be invalidated as

  9.      * well. This is usually true for a full invalidate, but may be set to false if the

  10.      * View’s contents or dimensions have not changed.

  11.      */

  12.     void invalidate(boolean invalidateCache) {

  13.         if (ViewDebug.TRACE_HIERARCHY) {

  14.             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);

  15.         }

  16.         if (skipInvalidate()) {

  17.             return;

  18.         }

  19.         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||

  20.                 (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||

  21.                 (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {

  22.             mLastIsOpaque = isOpaque();

  23.             mPrivateFlags &= ~DRAWN;

  24.             mPrivateFlags |= DIRTY;

  25.             if (invalidateCache) {

  26.                 mPrivateFlags |= INVALIDATED;

  27.                 mPrivateFlags &= ~DRAWING_CACHE_VALID;

  28.             }

  29.             final AttachInfo ai = mAttachInfo;

  30.             final ViewParent p = mParent;

  31.             //noinspection PointlessBooleanExpression,ConstantConditions

  32.             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {

  33.                 if (p != null && ai != null && ai.mHardwareAccelerated) {

  34.                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy

  35.                     // with a null dirty rect, which tells the ViewAncestor to redraw everything

  36.                     p.invalidateChild(this, null);

  37.                     return;

  38.                 }

  39.             }

  40.             if (p != null && ai != null) {

  41.                 final Rect r = ai.mTmpInvalRect;

  42.                 r.set(0, 0, mRight - mLeft, mBottom - mTop);

  43.                 // Don’t call invalidate – we don’t want to internally scroll

  44.                 // our own bounds

  45.                 p.invalidateChild(this, r);

  46.             }

  47.         }

  48.     }

下面我们来具体进行分析invalidate(true)函数的执行流程: 1、首先调用skipInvalidate(),该函数主要判断该View是否不需要重绘,如果不许要重绘则直接返回,不需要重绘的条件是该View不可见并且未进行动画 2、接下来的if语句是来进一步判断View是否需要绘制,其中表达式 (mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)的意思指的是如果View需要重绘并且其大小不为0,其余几个本人也未完全理解,还望高手指点~~如果需要重绘,则处理相关标志位 3、对于开启硬件加速的应用程序,则调用父视图的invalidateChild函数绘制整个区域,否则只绘制dirty区域(r变量所指的区域),这是一个向上回溯的过程,每一层的父View都将自己的显示区域与传入的刷新Rect做交集。 接下来看invalidateChild()的 实现过程:

[java] view plaincopy

  1. public final void invalidateChild(View child, final Rect dirty) {

  2.     if (ViewDebug.TRACE_HIERARCHY) {

  3.         ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD);

  4.     }

  5.     ViewParent parent = this;

  6.     final AttachInfo attachInfo = mAttachInfo;

  7.     if (attachInfo != null) {

  8.         // If the child is drawing an animation, we want to copy this flag onto

  9.         // ourselves and the parent to make sure the invalidate request goes

  10.         // through

  11.         final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;

  12.         if (dirty == null) {

  13.             if (child.mLayerType != LAYER_TYPE_NONE) {

  14.                 mPrivateFlags |= INVALIDATED;

  15.                 mPrivateFlags &= ~DRAWING_CACHE_VALID;

  16.                 child.mLocalDirtyRect.setEmpty();

  17.             }

  18.             do {

  19.                 View view = null;

  20.                 if (parent instanceof View) {

  21.                     view = (View) parent;

  22.                     if (view.mLayerType != LAYER_TYPE_NONE) {

  23.                         view.mLocalDirtyRect.setEmpty();

  24.                         if (view.getParent() instanceof View) {

  25.                             final View grandParent = (View) view.getParent();

  26.                             grandParent.mPrivateFlags |= INVALIDATED;

  27.                             grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;

  28.                         }

  29.                     }

  30.                     if ((view.mPrivateFlags & DIRTY_MASK) != 0) {

  31.                         // already marked dirty - we’re done

  32.                         break;

  33.                     }

  34.                 }

  35.                 if (drawAnimation) {

  36.                     if (view != null) {

  37.                         view.mPrivateFlags |= DRAW_ANIMATION;

  38.                     } else if (parent instanceof ViewRootImpl) {

  39.                         ((ViewRootImpl) parent).mIsAnimating = true;

  40.                     }

  41.                 }

  42.                 if (parent instanceof ViewRootImpl) {

  43.                     ((ViewRootImpl) parent).invalidate();

  44.                     parent = null;

  45.                 } else if (view != null) {

  46.                     if ((view.mPrivateFlags & DRAWN) == DRAWN ||

  47.                             (view.mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {

  48.                         view.mPrivateFlags &= ~DRAWING_CACHE_VALID;

  49.                         view.mPrivateFlags |= DIRTY;

  50.                         parent = view.mParent;

  51.                     } else {

  52.                         parent = null;

  53.                     }

  54.                 }

  55.             } while (parent != null);

  56.         } else {

  57.             // Check whether the child that requests the invalidate is fully opaque

  58.             final boolean isOpaque = child.isOpaque() && !drawAnimation &&

  59.                     child.getAnimation() == null;

  60.             // Mark the child as dirty, using the appropriate flag

  61.             // Make sure we do not set both flags at the same time

  62.             int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;

  63.             if (child.mLayerType != LAYER_TYPE_NONE) {

  64.                 mPrivateFlags |= INVALIDATED;

  65.                 mPrivateFlags &= ~DRAWING_CACHE_VALID;

  66.                 child.mLocalDirtyRect.union(dirty);

  67.             }

  68.             final int[] location = attachInfo.mInvalidateChildLocation;

  69.             location[CHILD_LEFT_INDEX] = child.mLeft;

  70.             location[CHILD_TOP_INDEX] = child.mTop;

  71.             Matrix childMatrix = child.getMatrix();

  72.             if (!childMatrix.isIdentity()) {

  73.                 RectF boundingRect = attachInfo.mTmpTransformRect;

  74.                 boundingRect.set(dirty);

  75.                 //boundingRect.inset(-0.5f, -0.5f);

  76.                 childMatrix.mapRect(boundingRect);

  77.                 dirty.set((int) (boundingRect.left - 0.5f),

  78.                         (int) (boundingRect.top - 0.5f),

  79.                         (int) (boundingRect.right + 0.5f),

  80.                         (int) (boundingRect.bottom + 0.5f));

  81.             }

  82.             do {

  83.                 View view = null;

  84.                 if (parent instanceof View) {

  85.                     view = (View) parent;

  86.                     if (view.mLayerType != LAYER_TYPE_NONE &&

  87.                             view.getParent() instanceof View) {

  88.                         final View grandParent = (View) view.getParent();

  89.                         grandParent.mPrivateFlags |= INVALIDATED;

  90.                         grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;

  91.                     }

  92.                 }

  93.                 if (drawAnimation) {

  94.                     if (view != null) {

  95.                         view.mPrivateFlags |= DRAW_ANIMATION;

  96.                     } else if (parent instanceof ViewRootImpl) {

  97.                         ((ViewRootImpl) parent).mIsAnimating = true;

  98.                     }

  99.                 }

  100.                 // If the parent is dirty opaque or not dirty, mark it dirty with the opaque

  101.                 // flag coming from the child that initiated the invalidate

  102.                 if (view != null) {

  103.                     if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&

  104.                             view.getSolidColor() == 0) {

  105.                         opaqueFlag = DIRTY;

  106.                     }

  107.                     if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {

  108.                         view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;

  109.                     }

  110.                 }

  111.                 parent = parent.invalidateChildInParent(location, dirty);

  112.                 if (view != null) {

  113.                     // Account for transform on current parent

  114.                     Matrix m = view.getMatrix();

  115.                     if (!m.isIdentity()) {

  116.                         RectF boundingRect = attachInfo.mTmpTransformRect;

  117.                         boundingRect.set(dirty);

  118.                         m.mapRect(boundingRect);

  119.                         dirty.set((int) boundingRect.left, (int) boundingRect.top,

  120.                                 (int) (boundingRect.right + 0.5f),

  121.                                 (int) (boundingRect.bottom + 0.5f));

  122.                     }

  123.                 }

  124.             } while (parent != null);

  125.         }

  126.     }

  127. }

  大概流程如下,我们主要关注dirty区域不是null(非硬件加速)的情况: 1、判断子视图是否是不透明的(不透明的条件是isOpaque()返回true,视图未进行动画以及child.getAnimation() == null),并将判断结果保存到变量isOpaque中,如果不透明则将变量opaqueFlag设置为DIRTY_OPAQUE,否则设置为DIRTY。 2、定义location保存子视图的左上角坐标 3、如果子视图正在动画,那么父视图也要添加动画标志,如果父视图是ViewGroup,那么给mPrivateFlags添加DRAW_ANIMATION标识,如果父视图是ViewRoot,则给其内部变量mIsAnimating赋值为true 4、设置dirty标识,如果子视图是不透明的,则父视图设置为DIRTY_OPAQUE,否则设置为DIRTY 5、调用parent.invalidateChildInparent(),这里的parent有可能是ViewGroup,也有可能是ViewRoot(最后一次while循环),首先来看ViewGroup, ViewGroup中该函数的主要作用是对dirty区域进行计算 以上过程的主体是一个do{}while{}循环,不断的将子视图的dirty区域与父视图做运算来确定最终要重绘的dirty区域,最终循环到ViewRoot(ViewRoot的parent为null)为止,并将dirty区域保存到ViewRoot的mDirty变量中

[java] view plaincopy

  1. /**

  2.      * Don’t call or override this method. It is used for the implementation of

  3.      * the view hierarchy.

  4.      *

  5.      * This implementation returns null if this ViewGroup does not have a parent,

  6.      * if this ViewGroup is already fully invalidated or if the dirty rectangle

  7.      * does not intersect with this ViewGroup’s bounds.

  8.      */

  9.     public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {

  10.         if (ViewDebug.TRACE_HIERARCHY) {

  11.             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD_IN_PARENT);

  12.         }

  13.         if ((mPrivateFlags & DRAWN) == DRAWN ||

  14.                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {

  15.             if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=

  16.                         FLAG_OPTIMIZE_INVALIDATE) {

  17.                 dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,

  18.                         location[CHILD_TOP_INDEX] - mScrollY);

  19.                 final int left = mLeft;

  20.                 final int top = mTop;

  21.                 if ((mGroupFlags & FLAG_CLIP_CHILDREN) != FLAG_CLIP_CHILDREN ||

  22.                         dirty.intersect(0, 0, mRight - left, mBottom - top) ||

  23.                         (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {

  24.                     mPrivateFlags &= ~DRAWING_CACHE_VALID;

  25.                     location[CHILD_LEFT_INDEX] = left;

  26.                     location[CHILD_TOP_INDEX] = top;

  27.                     if (mLayerType != LAYER_TYPE_NONE) {

  28.                         mLocalDirtyRect.union(dirty);

  29.                     }

  30.                     return mParent;

  31.                 }

  32.             } else {

  33.                 mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;

  34.                 location[CHILD_LEFT_INDEX] = mLeft;

  35.                 location[CHILD_TOP_INDEX] = mTop;

  36.                 if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {

  37.                     dirty.set(0, 0, mRight - mLeft, mBottom - mTop);

  38.                 } else {

  39.                     // in case the dirty rect extends outside the bounds of this container

  40.                     dirty.union(0, 0, mRight - mLeft, mBottom - mTop);

  41.                 }

  42.                 if (mLayerType != LAYER_TYPE_NONE) {

  43.                     mLocalDirtyRect.union(dirty);

  44.                 }

  45.                 return mParent;

  46.             }

  47.         }

  48.         return null;

  49.     }

该函数首先调用offset将子视图的坐标位置转换为在父视图(当前视图)的显示位置,这里主要考虑scroll后导致子视图在父视图中的显示区域会发生变化,接着调用union函数求得当前视图与子视图的交集,求得的交集必定是小于dirty的范围,因为子视图的dirty区域有可能超出其父视图(当前视图)的范围,最后返回当前视图的父视图。 再来看ViewRoot中invalidateChildInparent的执行过程:

[java] view plaincopy

  1. public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
  2.         invalidateChild(null, dirty);
  3.         return null;
  4.     }

该函数仅仅调用了ViewRoot的invalidateChild,下面继续看invalidateChild的源码:

[java] view plaincopy

  1. public void invalidateChild(View child, Rect dirty) {
  2.         checkThread();
  3.         if (DEBUG_DRAW) Log.v(TAG, “Invalidate child: “ + dirty);
  4.         if (dirty == null) {
  5.             // Fast invalidation for GL-enabled applications; GL must redraw everything
  6.             invalidate();
  7.             return;
  8.         }
  9.         if (mCurScrollY != 0 || mTranslator != null) {
  10.             mTempRect.set(dirty);
  11.             dirty = mTempRect;
  12.             if (mCurScrollY != 0) {
  13.                dirty.offset(0, -mCurScrollY);
  14.             }
  15.             if (mTranslator != null) {
  16.                 mTranslator.translateRectInAppWindowToScreen(dirty);
  17.             }
  18.             if (mAttachInfo.mScalingRequired) {
  19.                 dirty.inset(-1, -1);
  20.             }
  21.         }
  22.         if (!mDirty.isEmpty() && !mDirty.contains(dirty)) {
  23.             mAttachInfo.mSetIgnoreDirtyState = true;
  24.             mAttachInfo.mIgnoreDirtyState = true;
  25.         }
  26.         mDirty.union(dirty);
  27.         if (!mWillDrawSoon) {
  28.             scheduleTraversals();
  29.         }
  30.     }

具体分析如下: 1、判断此次调用是否在UI线程中进行 2、将dirty的坐标位置转换为ViewRoot的屏幕显示区域 3、更新mDirty变量,并调用scheduleTraversals发起重绘请求 至此一次invalidate()就结束了 总结:invalidate主要给需要重绘的视图添加DIRTY标记,并通过和父视图的矩形运算求得真正需要绘制的区域,并保存在ViewRoot中的mDirty变量中,最后调用scheduleTraversals发起重绘请求,scheduleTraversals会发送一个异步消息,最终调用performTraversals()执行重绘,performTraversals()的具体过程以后再分析。 以上所有代码基于Android 4.0.4,并结合《Android内核剖析》分析总结而成,源码中涉及到的部分细节本人也未完全理解,还望高手指点~~

select case order_state when ‘0’ then ‘已取消’ when ‘10’ then ‘已下单’ when ‘20’ then if(payment_code = ‘offline’,’货到付款’,’已付款’) when ‘30’ then ‘已发货’ when ‘40’ then ‘已完成’ end from shopnc_order;

1.修改成中文

$g_default_language = ‘english’;//582

修改成

$g_default_language = ‘chinese_simplified’;

2.管理员添加可直接弄密码

$g_send_reset_password = ON;//257

修改成

$g_send_reset_password = OFF;

0%