程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 若何應用C#讀寫鎖ReaderWriterLockSlim

若何應用C#讀寫鎖ReaderWriterLockSlim

編輯:C#入門知識

若何應用C#讀寫鎖ReaderWriterLockSlim。本站提示廣大學習愛好者:(若何應用C#讀寫鎖ReaderWriterLockSlim)文章只能為提供參考,不一定能成為您想要的結果。以下是若何應用C#讀寫鎖ReaderWriterLockSlim正文


View的膩滑轉動後果

甚麼是完成View的膩滑轉動後果呢,舉個簡略的例子,一個View從在我們指定的時光內從一個地位轉動到別的一個地位,我們應用Scroller類可以完成勻速轉動,可以先加快後加速,可以先加速後加快等等後果,而不是剎時的挪動的後果,所以Scroller可以幫我們完成許多滑動的後果。

起首我們先來看一下Scroller的用法,根本可歸納綜合為“三部曲”:

1、創立一個Scroller對象,普通在View的結構器中創立:

public ScrollViewGroup(Context context) {
  this(context, null);
}

public ScrollViewGroup(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
}

public ScrollViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  mScroller = new Scroller(context);
}

2、重寫View的computeScroll()辦法,上面的代碼根本是不會變更的:

@Override
public void computeScroll() {
  super.computeScroll();
  if (mScroller.computeScrollOffset()) {
    scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    postInvalidate();
  }
}

3、挪用startScroll()辦法,startX和startY為開端轉動的坐標點,dx和dy為對應的偏移量:

mScroller.startScroll (int startX, int startY, int dx, int dy);
invalidate();

下面的三步就是Scroller的根本用法了。

那接上去的義務就是解析Scroller的轉動道理了。

而在這之前,我們還有一件事要辦,那就是弄清晰scrollTo()scrollBy()的道理。scrollTo()scrollBy()的差別我這裡就不反復論述了,不懂的可以自行谷歌或百度。

上面貼出scrollTo()的源碼:

public void scrollTo(int x, int y) {
  if (mScrollX != x || mScrollY != y) {
    int oldX = mScrollX;
    int oldY = mScrollY;
    mScrollX = x;
    mScrollY = y;
    invalidateParentCaches();
    onScrollChanged(mScrollX, mScrollY, oldX, oldY);
    if (!awakenScrollBars()) {
      postInvalidateOnAnimation();
    }
  }
}

設置好mScrollXmScrollY以後,挪用了onScrollChanged(mScrollX, mScrollY, oldX, oldY);  ,View就會被從新繪制。如許就到達了滑動的後果。

上面我們再來看看scrollBy()  :

public void scrollBy(int x, int y) {
  scrollTo(mScrollX + x, mScrollY + y);
}

如許冗長的代碼信任年夜家都懂了,本來scrollBy()外部是挪用了scrollTo()的。然則scrollTo() / scrollBy()的轉動都是剎時完成的,怎樣樣能力完成膩滑轉動呢。

不曉得年夜家有無如許一種設法主意:假如我們把要轉動的偏移量分紅若干份小的偏移量,固然這分量要年夜。然後用scrollTo() / scrollBy()每次都轉動小份的偏移量。在必定的時光內,不就成了膩滑轉動了嗎?沒錯,Scroller恰是借助這一道理來完成膩滑轉動的。

上面我們就來看看源碼吧!

依據“三部曲”中第一部,先來看看Scroller的結構器:

public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
  mFinished = true;
  if (interpolator == null) {
    mInterpolator = new ViscousFluidInterpolator();
  } else {
    mInterpolator = interpolator;
  }
  mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
  mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
  mFlywheel = flywheel;

  mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
}

在結構器中做的重要就是指定了插補器,假如沒有指定插補器,那末就用默許的ViscousFluidInterpolator

我們再來看看Scroller的startScroll()

public void startScroll(int startX, int startY, int dx, int dy, int duration) {
  mMode = SCROLL_MODE;
  mFinished = false;
  mDuration = duration;
  mStartTime = AnimationUtils.currentAnimationTimeMillis();
  mStartX = startX;
  mStartY = startY;
  mFinalX = startX + dx;
  mFinalY = startY + dy;
  mDeltaX = dx;
  mDeltaY = dy;
  mDurationReciprocal = 1.0f / (float) mDuration;
}

我們發明,在startScroll()外面並沒有開端轉動,而是設置了一堆變量的初始值,那末究竟是甚麼讓View開端轉動的?我們應當把目的集中在startScroll()的下一句invalidate();身上。我們可以如許懂得:起首在startScroll()設置好了一堆初始值,以後挪用了invalidate();讓View從新繪制,這裡又有一個很主要的點,在draw()中會挪用computeScroll()這個辦法!

源碼太長了,在這裡就不貼出來了。想看的童鞋在View類外面搜boolean draw(Canvas canvas, ViewGroup parent, long drawingTime)這個辦法就可以看到了。經由過程ViewGroup.drawChild()辦法就會挪用子View的draw()辦法。而在View類外面的computeScroll()是一個空的辦法,須要我們去完成:

/**
 * Called by a parent to request that a child update its values for mScrollX
 * and mScrollY if necessary. This will typically be done if the child is
 * animating a scroll using a {@link android.widget.Scroller Scroller}
 * object.
 */
public void computeScroll() {
}

而在下面“三部曲”的第二部中,我們就曾經完成了computeScroll()  。起首斷定了computeScrollOffset() ,我們來看看相干源碼:

/**
 * Call this when you want to know the new location. If it returns true,
 * the animation is not yet finished.
 */ 
public boolean computeScrollOffset() {
  if (mFinished) {
    return false;
  }

  int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);

  if (timePassed < mDuration) {
    switch (mMode) {
    case SCROLL_MODE:
      final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
      mCurrX = mStartX + Math.round(x * mDeltaX);
      mCurrY = mStartY + Math.round(x * mDeltaY);
      break;
    case FLING_MODE:
      final float t = (float) timePassed / mDuration;
      final int index = (int) (NB_SAMPLES * t);
      float distanceCoef = 1.f;
      float velocityCoef = 0.f;
      if (index < NB_SAMPLES) {
        final float t_inf = (float) index / NB_SAMPLES;
        final float t_sup = (float) (index + 1) / NB_SAMPLES;
        final float d_inf = SPLINE_POSITION[index];
        final float d_sup = SPLINE_POSITION[index + 1];
        velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
        distanceCoef = d_inf + (t - t_inf) * velocityCoef;
      }

      mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
      
      mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
      // Pin to mMinX <= mCurrX <= mMaxX
      mCurrX = Math.min(mCurrX, mMaxX);
      mCurrX = Math.max(mCurrX, mMinX);
      
      mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
      // Pin to mMinY <= mCurrY <= mMaxY
      mCurrY = Math.min(mCurrY, mMaxY);
      mCurrY = Math.max(mCurrY, mMinY);

      if (mCurrX == mFinalX && mCurrY == mFinalY) {
        mFinished = true;
      }

      break;
    }
  }
  else {
    mCurrX = mFinalX;
    mCurrY = mFinalY;
    mFinished = true;
  }
  return true;
}

這個辦法的前往值有講求,若前往true則解釋Scroller的滑動沒有停止;若前往false解釋Scroller的滑動停止了。再來看看外部的代碼:先是盤算出了曾經滑動的時光,若曾經滑動的時光小於總滑動的時光,則解釋滑動沒有停止;否則就解釋滑動停止了,設置標志mFinished = true;  。而在滑動未停止外面又分為了兩個mode,不外這兩個mode都干了差不多的事,年夜致就是依據適才的時光timePassed和插補器來盤算出該時光點轉動的間隔mCurrXmCurrY。也就是下面“三部曲”中第二部的mScroller.getCurrX()  , mScroller.getCurrY()的值。

然後在第二部曲中挪用scrollTo()辦法轉動到指定點(即下面的mCurrX, mCurrY)。以後又挪用了postInvalidate(); ,讓View重繪偏重新挪用computeScroll()以此輪回下去,一向到View轉動到指定地位為止,至此Scroller轉動停止。

其實Scroller的道理照樣比擬淺顯易懂的。我們再來理清一下思緒,以一張圖的情勢來終結明天的Scroller解析:

總結

好了,本文引見Android中Scroller的轉動道理的內容到這就停止了,假如有甚麼成績可以鄙人面留言。願望本文的內容對年夜家開辟Android能有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved