首页 > 代码库 > Android字符串格式化开源库phrase介绍

Android字符串格式化开源库phrase介绍

       在上一篇博客Android通过String.format格式化(动态改变)字符串资源的显示内容中介绍了通过String.format来格式化string.xml文件中的字符串,本文介绍一个可以实现同样功能的开源库phrase,相比于String.format,通过phrase格式化字符串代码更具可读性。


一、phrase项目介绍:

1、源码:phrase项目的源代码很简单,里面总共只有一个类:Phrase.java,代码如下:

/*
 * Copyright (C) 2013 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uperone.stringformat;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import android.app.Fragment;
import android.content.Context;
import android.content.res.Resources;
import android.text.SpannableStringBuilder;
import android.view.View;

/**
 * A fluent API for formatting Strings. Canonical usage:
 * <pre>
 *   CharSequence formatted = Phrase.from("Hi {first_name}, you are {age} years old.")
 *       .put("first_name", firstName)
 *       .put("age", age)
 *       .format();
 * </pre>
 * <ul>
 * <li>Surround keys with curly braces; use two {{ to escape.</li>
 * <li>Keys start with lowercase letters followed by lowercase letters and underscores.</li>
 * <li>Spans are preserved, such as simple HTML tags found in strings.xml.</li>
 * <li>Fails fast on any mismatched keys.</li>
 * </ul>
 * The constructor parses the original pattern into a doubly-linked list of {@link Token}s.
 * These tokens do not modify the original pattern, thus preserving any spans.
 * <p/>
 * The {@link #format()} method iterates over the tokens, replacing text as it iterates. The
 * doubly-linked list allows each token to ask its predecessor for the expanded length.
 */
public final class Phrase {

  /** The unmodified original pattern. */
  private final CharSequence pattern;

  /** All keys parsed from the original pattern, sans braces. */
  private final Set<String> keys = new HashSet<String>();
  private final Map<String, CharSequence> keysToValues = new HashMap<String, CharSequence>();

  /** Cached result after replacing all keys with corresponding values. */
  private CharSequence formatted;

  /** The constructor parses the original pattern into this doubly-linked list of tokens. */
  private Token head;

  /** When parsing, this is the current character. */
  private char curChar;
  private int curCharIndex;

  /** Indicates parsing is complete. */
  private static final int EOF = 0;

  /**
   * Entry point into this API.
   *
   * @throws IllegalArgumentException if pattern contains any syntax errors.
   */
  public static Phrase from(Fragment f, int patternResourceId) {
    return from(f.getResources(), patternResourceId);
  }

  /**
   * Entry point into this API.
   *
   * @throws IllegalArgumentException if pattern contains any syntax errors.
   */
  public static Phrase from(View v, int patternResourceId) {
    return from(v.getResources(), patternResourceId);
  }

  /**
   * Entry point into this API.
   *
   * @throws IllegalArgumentException if pattern contains any syntax errors.
   */
  public static Phrase from(Context c, int patternResourceId) {
    return from(c.getResources(), patternResourceId);
  }

  /**
   * Entry point into this API.
   *
   * @throws IllegalArgumentException if pattern contains any syntax errors.
   */
  public static Phrase from(Resources r, int patternResourceId) {
    return from(r.getText(patternResourceId));
  }

  /**
   * Entry point into this API; pattern must be non-null.
   *
   * @throws IllegalArgumentException if pattern contains any syntax errors.
   */
  public static Phrase from(CharSequence pattern) {
    return new Phrase(pattern);
  }

  /**
   * Replaces the given key with a non-null value. You may reuse Phrase instances and replace
   * keys with new values.
   *
   * @throws IllegalArgumentException if the key is not in the pattern.
   */
  public Phrase put(String key, CharSequence value) {
    if (!keys.contains(key)) {
      throw new IllegalArgumentException("Invalid key: " + key);
    }
    if (value =http://www.mamicode.com/= null) {>


2、字符串格式化原理:

通过阅读Phrase.java的代码可知,它用"{"和"}"将需要格式化的内容包起来,然后用键值对给需要改变的内容传值,包起来的内容为键,值为动态设置的内容,比如:

"Hi {first_name}, you are {age} years old."
我们要最终的显示内容为:“Hi UperOne, you are 26 years old.”这里的first_name和age是键,值为UperOne和26。


二、使用方法:

Phrase.java的类名上面的注释已经告诉了我们具体的使用方法:

/**
 * A fluent API for formatting Strings. Canonical usage:
 * <pre>
 *   CharSequence formatted = Phrase.from("Hi {first_name}, you are {age} years old.")
 *       .put("first_name", firstName)
 *       .put("age", age)
 *       .format();
 * </pre>
 * <ul>
 * <li>Surround keys with curly braces; use two {{ to escape.</li>
 * <li>Keys start with lowercase letters followed by lowercase letters and underscores.</li>
 * <li>Spans are preserved, such as simple HTML tags found in strings.xml.</li>
 * <li>Fails fast on any mismatched keys.</li>
 * </ul>
 * The constructor parses the original pattern into a doubly-linked list of {@link Token}s.
 * These tokens do not modify the original pattern, thus preserving any spans.
 * <p/>
 * The {@link #format()} method iterates over the tokens, replacing text as it iterates. The
 * doubly-linked list allows each token to ask its predecessor for the expanded length.
 */
public final class Phrase

比如:

CharSequence parseStr = Phrase.from("Hi {first_name}, you are {age} years old.")
				 .put("first_name", "UperOne")
				 .put("age", "26")
				 .format();
		
mParseTxt.setText( parseStr );
用起来非常简单。



Android字符串格式化开源库phrase介绍