Hippy项目源码分析(二)

2021SC@SDUSC

首篇文章已说明我的分工:Core全部内容

目录

include\core\base\macros.h

include\core\base\string_view_utils.h

include\core\base\task.h

include\core\base\task_runner.h

include\core\base\thread.h

小结


 include\core\base\macros.h

#pragma once
#include <stddef.h>

// Suppress UNUSED warnings
#define HIPPY_USE(expr) \
  do {                  \
    (void)(expr);       \
  } while (0)

// Calculate size of array
#define arraysize(array) (sizeof(ArraySizeHelper(array)))

template <typename CharType, size_t N>
char (&ArraySizeHelper(CharType (&array)[N]))[N];

// Suppress copy
#define DISALLOW_COPY_AND_ASSIGN(Type) \
  Type(const Type&) = delete;          \
  Type& operator=(const Type&) = delete

// Enable move and suppress copy
#define MOVE_ONLY(Type)                       \
  Type(Type&&) noexcept = default;            \
  Type& operator=(Type&&) noexcept = default; \
  DISALLOW_COPY_AND_ASSIGN(Type)

宏定义,这里面就放各各宏的头文件,然后在PCH文件中引用着这个一个头文件就OK

include\core\base\string_view_utils.h

#pragma once

#include <codecvt>
#include <locale>
#include <string>
#include <utility>

#include "base/logging.h"
#include "base/unicode_string_view.h"

#define EXTEND_LITERAL(ch) ch, ch, u##ch, U##ch

namespace hippy {
namespace base {

class StringViewUtils {
 public:
  using unicode_string_view = tdf::base::unicode_string_view;
  using u8string = unicode_string_view::u8string;
  using char8_t_ = unicode_string_view::char8_t_;

  inline static bool IsEmpty(const unicode_string_view& str_view) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Unkown: {
        return true;
      }
      case unicode_string_view::Encoding::Latin1: {
        return str_view.latin1_value().empty();
      }
      case unicode_string_view::Encoding::Utf16: {
        return str_view.utf16_value().empty();
      }
      case unicode_string_view::Encoding::Utf32: {
        return str_view.utf32_value().empty();
      }
      case unicode_string_view::Encoding::Utf8: {
        return str_view.utf8_value().empty();
      }
      default:
        break;
    }

    TDF_BASE_NOTREACHED();
    return true;
  }

  static unicode_string_view CovertToLatin(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(str_view.latin1_value());
      }
      case unicode_string_view::Encoding::Utf16:
      case unicode_string_view::Encoding::Utf32:
      case unicode_string_view::Encoding::Utf8:
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view CovertToUtf16(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(
            CopyChars<char, char16_t>(str_view.latin1_value()));
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(str_view.utf16_value());
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(U32ToU16(str_view.utf32_value()));
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(U8ToU16(str_view.utf8_value()));
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view CovertToUtf32(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(
            CopyChars<char, char32_t>(str_view.latin1_value()));
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(U16ToU32(str_view.utf16_value()));
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(str_view.utf32_value());
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(U8ToU32(str_view.utf8_value()));
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view CovertToUtf8(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const auto& str = str_view.latin1_value();
        auto ptr =
            reinterpret_cast<const unicode_string_view::char8_t_*>(str.c_str());
        return unicode_string_view(ptr, str.length());
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(U16ToU8(str_view.utf16_value()));
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(U32ToU8(str_view.utf32_value()));
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(str_view.utf8_value());
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view Convert(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding dst_encoding) {
    unicode_string_view::Encoding src_encoding = str_view.encoding();
    switch (dst_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return CovertToLatin(str_view, src_encoding);
      }
      case unicode_string_view::Encoding::Utf16: {
        return CovertToUtf16(str_view, src_encoding);
      }
      case unicode_string_view::Encoding::Utf32: {
        return CovertToUtf32(str_view, src_encoding);
      }
      case unicode_string_view::Encoding::Utf8: {
        return CovertToUtf8(str_view, src_encoding);
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  inline static const char* U8ToConstCharPointer(
      const unicode_string_view::char8_t_* p) {
    return reinterpret_cast<const char*>(p);
  }

  inline static const unicode_string_view::char8_t_* ToU8Pointer(
      const char* p) {
    return reinterpret_cast<const unicode_string_view::char8_t_*>(p);
  }

  inline static const char* ToConstCharPointer(
      const unicode_string_view& str_view,
      unicode_string_view& view_owner) {
    TDF_BASE_DCHECK(view_owner.encoding() ==
                    unicode_string_view::Encoding::Utf8);
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return str_view.latin1_value().c_str();
      }
      case unicode_string_view::Encoding::Utf8: {
        return U8ToConstCharPointer(str_view.utf8_value().c_str());
      }
      case unicode_string_view::Encoding::Utf16:
      case unicode_string_view::Encoding::Utf32: {
        unicode_string_view::u8string& ref = view_owner.utf8_value();
        ref =
            Convert(str_view, unicode_string_view::Encoding::Utf8).utf8_value();
        return U8ToConstCharPointer(ref.c_str());
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    TDF_BASE_NOTREACHED();
    return nullptr;
  }

  inline static unicode_string_view ConstCharPointerToStrView(const char* p,
                                                              size_t len = -1) {
    size_t length;
    if (len == -1) {
      length = strlen(p);
    } else {
      length = len;
    }
    return unicode_string_view(
        reinterpret_cast<const unicode_string_view::char8_t_*>(p), length);
  }

  inline static std::string ToU8StdStr(const unicode_string_view& str_view) {
    unicode_string_view::u8string str =
        Convert(str_view, unicode_string_view::Encoding::Utf8).utf8_value();
    return std::string(U8ToConstCharPointer(str.c_str()), str.length());
  }

  inline static size_t FindLastOf(const unicode_string_view& str_view,
                                  unicode_string_view::char8_t_ u8_ch,
                                  char ch,
                                  char16_t u16_ch,
                                  char32_t u32_ch) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const std::string& str = str_view.latin1_value();
        return str.find_last_of(ch);
        break;
      }
      case unicode_string_view::Encoding::Utf16: {
        const std::u16string& str = str_view.utf16_value();
        return str.find_last_of(u16_ch);
        break;
      }
      case unicode_string_view::Encoding::Utf32: {
        const std::u32string& str = str_view.utf32_value();
        return str.find_last_of(u32_ch);
        break;
      }
      case unicode_string_view::Encoding::Utf8: {
        const unicode_string_view::u8string& str = str_view.utf8_value();
        return str.find_last_of(u8_ch);
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }

    TDF_BASE_NOTREACHED();
    return 0;
  }

  inline static unicode_string_view SubStr(const unicode_string_view& str_view,
                                           size_t pos,
                                           size_t n) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const std::string& str = str_view.latin1_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      case unicode_string_view::Encoding::Utf16: {
        const std::u16string& str = str_view.utf16_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      case unicode_string_view::Encoding::Utf32: {
        const std::u32string& str = str_view.utf32_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      case unicode_string_view::Encoding::Utf8: {
        const unicode_string_view::u8string& str = str_view.utf8_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }

    TDF_BASE_NOTREACHED();
    return unicode_string_view();
  }

  inline static size_t GetLength(const unicode_string_view& str_view) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const std::string& str = str_view.latin1_value();
        return str.length();
        break;
      }
      case unicode_string_view::Encoding::Utf16: {
        const std::u16string& str = str_view.utf16_value();
        return str.length();
        break;
      }
      case unicode_string_view::Encoding::Utf32: {
        const std::u32string& str = str_view.utf32_value();
        return str.length();
        break;
      }
      case unicode_string_view::Encoding::Utf8: {
        const unicode_string_view::u8string& str = str_view.utf8_value();
        return str.length();
        break;
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }

    TDF_BASE_NOTREACHED();
    return 0;
  }

 private:
  template <typename SrcChar, typename DstChar>
  inline static std::basic_string<DstChar> CopyChars(
      const std::basic_string<SrcChar>& src) {
    static_assert(sizeof(SrcChar) <= sizeof(DstChar), "copy downgrade");

    size_t len = src.length();
    std::basic_string<DstChar> dst;
    dst.resize(len);
    std::copy_n(src.c_str(), len, &dst[0]);
    return dst;
  }

  inline static unicode_string_view::u8string U32ToU8(
      const std::u32string& str) {
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    std::string bytes = conv.to_bytes(str);
    const unicode_string_view::char8_t_* ptr =
        reinterpret_cast<const unicode_string_view::char8_t_*>(bytes.data());
    return unicode_string_view::u8string(ptr, bytes.length());
  }

  inline static std::u32string U8ToU32(
      const unicode_string_view::u8string& str) {
    const char* ptr = reinterpret_cast<const char*>(str.c_str());
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    return conv.from_bytes(ptr, ptr + str.length());
  }

  inline static unicode_string_view::u8string U16ToU8(
      const std::u16string& str) {
    std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
    std::string bytes = convert.to_bytes(str);
    const unicode_string_view::char8_t_* ptr =
        reinterpret_cast<const unicode_string_view::char8_t_*>(bytes.data());
    return unicode_string_view::u8string(ptr, bytes.length());
  }

  inline static std::u16string U8ToU16(
      const unicode_string_view::u8string& str) {
    const char* ptr = reinterpret_cast<const char*>(str.c_str());
    std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
    return convert.from_bytes(ptr, ptr + str.length());
  }

  inline static std::u16string U32ToU16(const std::u32string& str) {
    std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> convert;
    std::string bytes = convert.to_bytes(str);
    return std::u16string(reinterpret_cast<const char16_t*>(bytes.c_str()),
                          bytes.length() / sizeof(char16_t));
  }

  inline static std::u32string U16ToU32(const std::u16string& str) {
    const char16_t* ptr = str.c_str();
    std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> convert;
    return convert.from_bytes(
        reinterpret_cast<const char*>(ptr),
        reinterpret_cast<const char*>(ptr + str.length()));
  }
};

}  // namespace base
}  // namespace hippy

namespace tdf {
namespace base {

inline unicode_string_view operator+(const unicode_string_view& lhs,
                                     const unicode_string_view& rhs) {
  using StringViewUtils = hippy::base::StringViewUtils;
  unicode_string_view::unicode_string_view::Encoding lhs_encoding =
      lhs.encoding();
  unicode_string_view::Encoding rhs_encoding = rhs.encoding();
  if (lhs_encoding <= rhs_encoding) {
    switch (rhs_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).latin1_value() +
            rhs.latin1_value());
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).utf16_value() +
            rhs.utf16_value());
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).utf32_value() +
            rhs.utf32_value());
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).utf8_value() +
            rhs.utf8_value());
      }
      default: {
        TDF_BASE_NOTREACHED();
        return unicode_string_view();
      }
    }
  }

  switch (lhs_encoding) {
    case unicode_string_view::Encoding::Latin1: {
      return unicode_string_view(
          lhs.latin1_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).latin1_value());
    }
    case unicode_string_view::Encoding::Utf16: {
      return unicode_string_view(
          lhs.utf16_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).utf16_value());
    }
    case unicode_string_view::Encoding::Utf32: {
      return unicode_string_view(
          lhs.utf32_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).utf32_value());
    }
    case unicode_string_view::Encoding::Utf8: {
      return unicode_string_view(
          lhs.utf8_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).utf8_value());
    }
    default: {
      TDF_BASE_NOTREACHED();
    }
  }
  return unicode_string_view();
}

}  // namespace base
}  // namespace tdf

 xUtils 一个 Android 公共库框架,主要包括四个部分:View,Db, Http, Bitmap 四个模块。

View 模块主要的功能是通过注解绑定 UI,资源,事件。

Db 模块是一个数据库 orm 框架, 简单的语句就能进行数据的操作。

Http 模块主要访问网络,支持同步,异步方式的请求,支持文件的下载。

Bitmap 模块是加载图片以及图片的处理, 支持加载本地,网络图片。而且支持图片的内存和本地缓存。

如果我们想对一些xUtils中没有提供的监听方法通过注解绑定时,可自定义注解,这里以SwipeRefreshLayout的下拉刷新为例。

1新建一个类,选择Annotation

2定义注解:

//注解使用的目标:方法
@Target(ElementType.METHOD)
//注解什么时候运行:运行时运行
@Retention(RetentionPolicy.RUNTIME)
//有三个参数
@EventBase(
//注解的接口类型
        listenerType = SwipeRefreshLayout.OnRefreshListener.class,
//set方法的名字
        listenerSetter = "setOnRefreshListener",
//方法的名字,是接口对象调用的方法名
        methodName = "onRefresh"
)
//仿照提供的ViewUtils中的方法注解写上属性
public @interface Refresh {
    int[] value();
    int[] parentId() default{0};
}

3在主函数中写一个方法,用注解绑定即已完成自定义:

  @Refresh(R.id.fragment_refresh)
    private void click() {
        Toast.makeText(getActivity(), "正在刷新", Toast.LENGTH_SHORT).show();
        handler.sendEmptyMessageAtTime(0,3000);
    }

include\core\base\task.h

#pragma once

#include <stdint.h>

namespace hippy {
namespace base {

class Task {
 public:
  using TaskId = uint32_t;

  Task();
  virtual ~Task() = default;
  virtual bool isPriorityTask() = 0;
  virtual void Run() = 0;

  TaskId id_;
  bool canceled_ = false;
};

}  // namespace base
}  // namespace hippy

virtual bool IsEmpty() const =0 表示IsEmpty()是一个纯虚函数返回值是bool型数据 并且还是一个常函数

bool,
布尔,表示真假的数据类型,IsEmpty()会返回两个值,真值是1,假的就是0
所在类只能做基类,并且这个函数内部代码不能修改类的数据

include\core\base\task_runner.h

#pragma once

#include <stdint.h>

#include <condition_variable>  // NOLINT(build/c++11)
#include <memory>
#include <mutex>  // NOLINT(build/c++11)
#include <queue>
#include <utility>
#include <vector>

#include "core/base/thread.h"

namespace hippy {
namespace base {

class Task;
class TaskRunner : public Thread {
 public:
  using DelayedTimeInMs = uint64_t;

  TaskRunner();
  virtual ~TaskRunner();

  void Run() override;
  void Terminate();
  void PostTask(std::shared_ptr<Task> task);
  void PostDelayedTask(std::shared_ptr<Task> task,
                       DelayedTimeInMs delay_in_mseconds);
  void CancelTask(std::shared_ptr<Task> task);

 protected:
  void PostTaskNoLock(std::shared_ptr<Task> task);
  std::shared_ptr<Task> popTaskFromDelayedQueueNoLock(DelayedTimeInMs now);
  std::shared_ptr<Task> GetNext();

 protected:
  bool is_terminated_;
  std::queue<std::shared_ptr<Task>> task_queue_;

  using DelayedEntry = std::pair<DelayedTimeInMs, std::shared_ptr<Task>>;
  struct DelayedEntryCompare {
    bool operator()(const DelayedEntry& left, const DelayedEntry& right) const {
      return left.first > right.first;
    }
  };
  std::priority_queue<DelayedEntry,
                      std::vector<DelayedEntry>,
                      DelayedEntryCompare>
      delayed_task_queue_;

  std::mutex mutex_;
  std::condition_variable cv_;
};

}  // namespace base
}  // namespace hippy

主要两项功能:执行次数的限制、执行时间的限制(即超时)。TaskRunner 旨在利用计时器分时执行方法提供一个相对简易的并行运行机制,其目的不但在于一般的延时执行任务,还可以同时进行多项任务。这样的话,任意个独立的任务都可以在任何时候开始,并彼此独立地运行。

能提供多线程的定时服务,该类提供了多线程任务的管理。你可以创建TaskRunner的一个实例,其次也可以自行创建实例。该类可保障每一个任务或服务都可以在任何时刻独立的运行,而不会影响其他的任务或服务的运行。

include\core\base\thread.h

#pragma once

#include <pthread.h>

#include "core/base/thread_id.h"

namespace hippy {
namespace base {

class Thread {
 public:
  class Options {
   public:
    Options() : name_("hippy:<unknown>"), stack_size_(0) {}
    explicit Options(const char* name, int stack_size = 0)
        : name_(name), stack_size_(stack_size) {}

    const char* name() const { return name_; }
    int stack_size() const { return stack_size_; }

   private:
    const char* name_;
    int stack_size_;
  };

 public:
  explicit Thread(const Options& options);
  virtual ~Thread();

  void SetName(const char* name);
  inline ThreadId Id() { return thread_id_; }
  static ThreadId GetCurrent();

  virtual void Run() = 0;
  void Start();
  void Join();

  inline const char* name() const { return name_; }

  static const int kMaxThreadNameLength = 16;

 protected:
  char name_[kMaxThreadNameLength];
  int stack_size_;
  pthread_t thread_;

  ThreadId thread_id_;
};

}  // namespace base
}  // namespace hippy

C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic> ,<thread>,<mutex>,

<thread>:该头文件主要声明了 std::thread 类,另外 std::this_thread 命名空间也在该头文件中。

从C++11开始,C++标准库已经支持了线程库了,其实在底层,仍旧使用的是平台相关的线程API
有了std::thread之后,我们就不用在不同的平台使用不同的API了,比如Unix平台使用pthread, windows平台使用WinSDK的CreateThread了,接口使用去掉了平台差异性,使得项目开发具有更好的移植性
 

小结

以上为本周学习内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值