HarmonyOS开发入门笔记 在线词典

简介: HarmonyOS开发入门笔记 在线词典

创建默认工程

创建工程时注意这里

service是不会在本地安装APP的

所以在选择service 时你在调试设备时时桌面时不会有图标的 image.png

通过下面这个位置我们可以启动自己的鸿蒙环境

image.png

然后看下我们的配置文件夹

image.png

找到main文件夹,其中config.json是我们的配置文件

image.png

具体可以查看

https://harmonyos.51cto.com/posts/7621

界面开发

<?xml version="1.0" encoding="utf-8"?>
<!--    整个界面-->
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical">
    <!--  缩窄两侧 和 上部  -->
    <DirectionalLayout
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:left_margin="20vp"
        ohos:right_margin="20vp"
        ohos:top_margin="40vp"
        ohos:background_element="#FFFAFA"
        ohos:orientation="vertical">
        <!--上半部分-->
        <DirectionalLayout
            ohos:height="50vp"
            ohos:width="match_parent"
            ohos:orientation="horizontal">
            <!--左侧文本框-->
            <!--        weight代表权重 设置此值之后 会线让其他元素填充区域后占满剩余区域 -->
            <!--        padding 内边距-->
            <!--        ohos:background_element="$graphic:select_border" 设置背景 这里使用了xml配置 通过xml可以设置边框等  也可以不使用xml直接赋给颜色值-->
            <TextField
                ohos:id="$+id:textField_ID"
                ohos:height="match_content"
                ohos:width="match_parent"
                ohos:hint="请输入要查找的单词"
                ohos:weight="1"
                ohos:background_element="$graphic:select_border"
                ohos:padding="2vp"
                ohos:text_size="20vp"
                ohos:hint_color="#FF4500"/>
            <!--右侧搜索按钮-->
            <Image
                ohos:id="$+id:sou_word"
                ohos:height="23vp"
                ohos:width="23vp"
                ohos:image_src="$media:sou"
                ohos:scale_mode="zoom_center"/>
        </DirectionalLayout>
        <!--搜索结果-->
<!--        layout_alignment="left|top"  文本对齐方式:左上角-->
<!--            visibility="hide"  设置隐藏-->
        <Text
            ohos:id="$+id:text_select_return"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:multiple_lines="true"
            ohos:background_element="$graphic:background_ability_main"
            ohos:visibility="hide"
            ohos:top_margin="40"
            ohos:layout_alignment="left|top"
            ohos:text_size="20vp"
            />
        <Image
            ohos:id="$+id:image"
            ohos:height="match_parent"
            ohos:width="match_parent"
            ohos:top_margin="60vp"
            ohos:image_src="$media:OIP_C"
            ohos:scale_mode="zoom_center"/>
    </DirectionalLayout>
</DirectionalLayout>

image.png

我们看到这里引用了select_border.xml这个文件

image.png

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid
        ohos:color="#FFFFFF"/>
    <stroke
        ohos:color="#00FFFF"
        ohos:width="1vp"
        />
</shape>

主要配置了边框和背景色

底层部分

这里先贴出鸿蒙官方的api开发文档

https://developer.harmonyos.com/cn/docs/documentation/doc-references/component-0000001054678683

爬取单词,封装sql

我们先从网站上爬出词库,并封装成sqlite

这里使用py来爬取

import os.path
import sqlite3
import requests
import re
words = {}
def add_word(word_line):
    global words
    result = re.split('[a-z]+\.',word_line)
    pattern = re.compile('[a-z]+\.')
    result2 = pattern.findall(word_line)
    word = result[0].strip()
    meanings = {}
    for i in range(0,len(result2)):
        key = result2[i].strip()
        value = result[i+1].strip()
        meanings[key] = value
    words[word] = meanings
r = requests.get('https://www.eol.cn/html/en/cetwords/cet4.shtml')
html = r.content
html_doc = str(html, 'utf-8')
print(html_doc)
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc,'lxml')
tags = soup.find_all(attrs={'class': 'wordL fl'})
for tag in tags:
    p_list = tag.select('p')
    for p in p_list:
        add_word(p.text)
print(words)
print('单词抓取完毕')
db_path = 'dict.sqlite'
if os.path.exists(db_path):
    os.remove(db_path)
conn = sqlite3.connect(db_path)
c = conn.cursor()
c.execute('''create table words
    (id int primary key not null,
    word varchar(30) not null,
    type  varchar(10) not null,
    meanings text not null);
    ''')
c.execute('create index word_index on words(word)')
conn.commit()
conn.close()
print("数据库创建完毕")
conn = sqlite3.connect(db_path)
c = conn.cursor()
i = 1
for word in words:
    value = words[word]
    for type in value:
        meanmings = value[type]
        sql = f'insert into words(id,word,type,meanings) values ( {i},"{word}","{type}","{meanmings}" )'
        c.execute(sql)
        print(sql)
        i += 1
    conn.commit()
conn.close()
print("生成完毕")

这时我们就得到了sqlite

sqlite文件操作类

我们在鸿蒙项目里创建sqlite类

package com.example.onlinedict.common;
import ohos.app.AbilityContext;
import ohos.data.DatabaseHelper;
import ohos.data.rdb.RdbOpenCallback;
import ohos.data.rdb.RdbStore;
import ohos.data.rdb.StoreConfig;
import ohos.global.resource.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
public class MyDict {
    //AbilityContext 是一个 Context 类,其功能是与系统环境进行交互,可以获取和改变一些与应用有关的属性值。
    private AbilityContext context;
    //词典数据库文件路径
    private File dictPath;
    //词典数据库文件
    private File dbPath;
    //鸿蒙数据库https://blog.csdn.net/dsbdsbdsb/article/details/112603421  及  https://harmonyos.51cto.com/posts/8013
    //数据
    private RdbStore rdbStore;
    private StoreConfig storeConfig=StoreConfig.newDefaultConfig("dict.sqlite");
    //创建数据库需要的回调  虽然这回调啥都不用写 但是需要有
    private static final RdbOpenCallback callback = new RdbOpenCallback() {
        @Override
        public void onCreate(RdbStore rdbStore) {
        }
        @Override
        public void onUpgrade(RdbStore rdbStore, int i, int i1) {
        }
    };
    //创建HAP私有路径
    public MyDict(AbilityContext context) {
        this.context = context;
        dictPath = new File(context.getDataDir().toString()+"/MainAbility/databases/db");
        if (!dictPath.exists()){//如果路径不存在就创建路径
            dictPath.mkdirs();
        }
        //获取文件
        dbPath = new File(Paths.get(dictPath.toString(),"dict.sqlite").toString());
    }
    //读取数据库文件拷贝到私有路径
    private void extractDB() throws IOException{
        //加载资源
        Resource resource = context.getResourceManager().getRawFileEntry("resources/rawfile/dict.sqlite").openRawFile();
        //如果路径为空 则删除  我也不知道为啥要写这个
        if (dbPath.exists()){
            dbPath.delete();
        }
        //输出流创建sqlite文件
        FileOutputStream fileOutputStream = new FileOutputStream(dbPath);
        //用于读取
        byte[] buffer = new byte[4096];
        int count = 0;
        while ((count=resource.read(buffer))>0){
            //将数组内容输出到文件中
            fileOutputStream.write(buffer,0,count);
        }
        resource.close();
        fileOutputStream.close();
    }
    //初始化
    public void init() throws IOException{
        //创建数据库
        extractDB();
        //打开数据库
        //数据库操作的辅助类
        DatabaseHelper helper = new DatabaseHelper(context);
        rdbStore = helper.getRdbStore(storeConfig,1,callback);
    }
}

调用初始化,添加前端监听事件

更改MainAbilitySlice文件

package com.example.onlinedict.slice;
import com.example.onlinedict.ResourceTable;
import com.example.onlinedict.common.MyDict;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import java.io.IOException;
public class MainAbilitySlice extends AbilitySlice {
    private MyDict myDict;
    private Image imageSearch;
    private Text textSelectReturn;
    private TextField textField_ID;
    private Image image;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        myDict = new MyDict(this);
        try {
            myDict.init();
        } catch (IOException e) {
            e.printStackTrace();
        }
        imageSearch = (Image) findComponentById(ResourceTable.Id_sou_word);
        textSelectReturn = (Text) findComponentById(ResourceTable.Id_text_select_return);
        textField_ID = (TextField) findComponentById(ResourceTable.Id_textField_ID);
        image = (Image) findComponentById(ResourceTable.Id_image);
        if (imageSearch!=null){
            imageSearch.setClickable(true);
            imageSearch.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    image.setVisibility(Component.HIDE);//下面图像不可见
                    textSelectReturn.setVisibility(Component.VISIBLE);
                    String s = textField_ID.getText();//获取文字
                }
            });
        }
    }
    @Override
    public void onActive() {
        super.onActive();
    }
    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

此时运行就可以实现点击搜索按钮下方图片隐藏

添加查询本地单词功能

为MyDict类添加方法

    /**
     * 搜索单词
     * @param word
     * @return
     */
    public List<DictBean> searchLocalWord(String word){
        //将其全部转换为小写
        word = word.toLowerCase();
        String[] args = new String[]{word};
        ResultSet resultSet = rdbStore.querySql("select * from words where word = ?",args);
        ArrayList<DictBean> dictBeans = new ArrayList<DictBean>();
        while (resultSet.goToNextRow()){
            DictBean dictBean = new DictBean();
            dictBean.setType(resultSet.getString(2));
            dictBean.setChineseWord(resultSet.getString(3));
            dictBeans.add(dictBean);
        }
        resultSet.close();
        return dictBeans;
    }

之后将监听器内的代码更改一下

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        //初始化本地词典
        myDict = new MyDict(this);
        try {
            myDict.init();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取前端控件的对象
        imageSearch = (Image) findComponentById(ResourceTable.Id_sou_word);
        textSelectReturn = (Text) findComponentById(ResourceTable.Id_text_select_return);
        textField_ID = (TextField) findComponentById(ResourceTable.Id_textField_ID);
        image = (Image) findComponentById(ResourceTable.Id_image);
        //添加搜索按钮监听
        if (imageSearch!=null){
            imageSearch.setClickable(true);
            imageSearch.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    selectWord();
                }
            });
        }
//        //添加文本框变更的监听器
//        textField_ID.addTextObserver(new Text.TextObserver() {
//            @Override
//            public void onTextUpdated(String s, int i, int i1, int i2) {
//                selectWord();
//            }
//        });
    }
  public void selectWord(){
        image.setVisibility(Component.HIDE);//下面图像不可见
        textSelectReturn.setVisibility(Component.VISIBLE);
        String s = textField_ID.getText();//获取文字
        List<DictBean> dictBeans = myDict.searchLocalWord(s);//获取list
        textSelectReturn.setText("");
        if (!dictBeans.isEmpty()){
            for (int i = 0; i < dictBeans.size(); i++) {
                textSelectReturn.append(dictBeans.get(i).getType()+" "+dictBeans.get(i).getChineseWord()+"\r\n");//添加文本内容
            }
        }
        else{
            textSelectReturn.setText("本地词库不存在此单词");
            myDict.searchWebWord(s,new SearchWordCallBackimpl());
        }
    }

添加网络爬虫搜索单词的功能

首先创建一个回调的接口ISearchWordCallBack

package com.example.onlinedict.common;
import com.example.onlinedict.common.bean.DictBean;
import java.util.List;
public interface ISearchWordCallBack {
    void onResult(List<DictBean> result);
}

之后创建线程类AsyncSearchWord

这里创建线程类的原因:主线程是ui线程 如果ui线程堵塞则程序会卡死,所以要再重新创建线程来在网络上查询

注意:这里用到了Jsoup这个jar包

package com.example.onlinedict.common;
import com.example.onlinedict.common.bean.DictBean;
import ohos.data.rdb.RdbStore;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.List;
class AsyncSearchWord extends Thread{
    private String word;
    private RdbStore rdbStore;
    private ISearchWordCallBack callBack;
    public AsyncSearchWord(String word,RdbStore rdbStore,ISearchWordCallBack callBack){
        this.word = word;
        this.callBack = callBack;
        this.rdbStore = rdbStore;
    }
    @Override
    public void run() {
        try{
            HiLogLabel label = new HiLogLabel(HiLog.LOG_APP ,223, "MY_RUN");
            //获取html
            String url="https://www.iciba.com/word?w=" + word;
            HiLog.warn(label, url+"/");
            Document document = Jsoup.connect(url).get();
            Elements ul = document.getElementsByClass("Mean_part__1Xi6p");
//            String sql = "insert into word(word ,type ,meanings ) values(?,?,?);";
            List<DictBean> dictBeans = new ArrayList<DictBean>();
            for (Element element : ul){
                //获取词义和词性
                Elements lis = element.getElementsByTag("li");
                HiLog.warn(label, lis.text()+"/listext");
                for (Element li:lis){
                    DictBean dictBean = new DictBean();
                    //词性
                    Elements itags = li.getElementsByTag("i");
                    for (Element itag:itags){
                        dictBean.setType(itag.text());
                        break;
                    }
                    //词义
                    Elements divs = li.getElementsByTag("div");
                    for (Element div :divs){
                        dictBean.setChineseWord(div.text());
                        break;
                    }
                    dictBeans.add(dictBean);
                    HiLog.warn(label, dictBean.toString()+"/");
//                    rdbStore.executeSql(sql,new String[]{word,dictBean.getType(),dictBean.getChineseWord()});
                }
                break;
            }
            if (callBack!=null){
                callBack.onResult(dictBeans);
            }
        }
        catch (Exception e){
            HiLogLabel label = new HiLogLabel(HiLog.LOG_APP ,223, "MY_errwo");
            HiLog.error(label, e.toString());
            e.printStackTrace();
        }
    }
}

在MyDict类中添加网络查询的方法,用于开启线程

    public void searchWebWord(String word , ISearchWordCallBack callBack){
        word = word.toLowerCase();
        HiLogLabel label = new HiLogLabel(HiLog.LOG_APP ,223, "MY_TAG");
        HiLog.error(label, word+"//");
        //异步搜索
        new AsyncSearchWord(word,rdbStore,callBack).start();
    }

添加MyEventHandler类负责主线程与网络线程的通信

 private class  MyEventHandler extends EventHandler {
        private List<DictBean> dictBeans;
        public MyEventHandler(EventRunner runner,List<DictBean> dictBeans) throws IllegalArgumentException {
            super(runner);
            this.dictBeans=dictBeans;
        }
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event==null){
                return;
            }
            int eventid = event.eventId;
            switch (eventid){
                case SEARCH_RESULT:{
                    if (dictBeans.size()==0){
                        textSelectReturn.setText("单词不存在");
                    }
                    else {
                        textSelectReturn.setText("");
                        for (int i = 0; i < dictBeans.size(); i++) {
                            textSelectReturn.append(dictBeans.get(i).getType()+" "+dictBeans.get(i).getChineseWord()+"\r\n");//添加文本内容
                        }
                    }
                    break;
                }
            }
        }
    }

创建回调的实现类

    private class SearchWordCallBackimpl implements ISearchWordCallBack{
        @Override
        public void onResult(List<DictBean> result) {
            //得到主线程
            EventRunner runner = EventRunner.getMainEventRunner();
            MyEventHandler eventHandler = new MyEventHandler(runner,result);
            eventHandler.sendEvent(SEARCH_RESULT);
            runner = null;
        }
    }

image.png

此时运行发现还是会无法访问,这是因为网络权限没有打开

image.png


相关文章
|
2天前
|
监控 开发者
鸿蒙5.0版开发:使用HiLog打印日志(ArkTS)
在HarmonyOS 5.0中,HiLog是系统提供的日志系统,支持DEBUG、INFO、WARN、ERROR、FATAL五种日志级别。本文介绍如何在ArkTS中使用HiLog打印日志,并提供示例代码。通过合理使用HiLog,开发者可以更好地调试和监控应用。
30 16
|
2天前
|
监控 UED 开发者
鸿蒙next版开发:订阅应用事件(ArkTS)
在HarmonyOS 5.0中,ArkTS引入了强大的应用事件订阅机制,允许开发者订阅和处理系统或应用级别的事件,这对于监控应用行为、优化用户体验和进行性能分析至关重要。本文详细介绍了如何在ArkTS中订阅应用事件,并提供了示例代码,包括导入模块、创建观察者、设置事件参数等步骤。通过这些方法,开发者可以更智能地管理和响应应用事件。
25 11
|
2天前
|
安全 API 数据处理
鸿蒙next版开发:ArkTS组件通用属性(隐私遮罩)
在HarmonyOS 5.0中,ArkTS引入了隐私遮罩功能,用于保护用户隐私和数据安全。本文详细介绍了隐私遮罩的通用属性和使用方法,并提供了示例代码。隐私遮罩支持Image和Text组件,在数据加载或处理过程中防止敏感信息泄露,提升用户体验和数据安全性。
22 11
|
1天前
|
UED
鸿蒙next版开发:相机开发-适配不同折叠状态的摄像头变更(ArkTS)
在HarmonyOS 5.0中,ArkTS提供了强大的相机开发能力,特别是针对折叠屏设备的摄像头适配。本文详细介绍了如何在ArkTS中检测和适配不同折叠状态下的摄像头变更,确保相机应用在不同设备状态下的稳定性和用户体验。通过代码示例展示了具体的实现步骤。
18 8
|
1天前
|
API 内存技术
鸿蒙next版开发:相机开发-拍照(ArkTS)
在HarmonyOS 5.0中,ArkTS提供了一套完整的API来管理相机功能,特别是拍照功能。本文详细介绍如何在ArkTS中实现拍照功能,包括导入接口、创建会话、配置会话、触发拍照及监听拍照输出流状态,并提供代码示例进行详细解读。通过本文,你将掌握如何在HarmonyOS 5.0中使用ArkTS实现高效的拍照功能。
18 7
|
1天前
|
监控 开发者
鸿蒙next版开发:使用HiDebug获取调试信息(ArkTS)
在HarmonyOS 5.0中,HiDebug是一个强大的应用调试工具,可帮助开发者获取系统的CPU使用率、内存信息等关键性能数据。本文详细介绍了如何在ArkTS中使用HiDebug,并提供了示例代码,帮助开发者进行性能分析和问题诊断。
16 7
|
2天前
|
开发者 容器
鸿蒙next版开发:ArkTS组件通用属性(文本通用)
在HarmonyOS 5.0中,ArkTS提供了丰富的文本通用属性,如textAlign、maxLines、textOverflow、fontSize、fontColor、fontStyle、fontWeight、fontFamily、lineHeight、letterSpacing和decoration等,用于实现多样的文本显示和样式效果。本文详细解读了这些属性,并提供了示例代码,帮助开发者更好地利用这些工具,提升应用界面的美观和实用性。
22 8
|
1天前
|
前端开发 API
鸿蒙next版开发:相机开发-预览(ArkTS)
在HarmonyOS 5.0中,使用ArkTS进行相机预览是核心功能之一。本文详细介绍了如何使用ArkTS实现相机预览,包括导入相机接口、创建Surface、获取相机输出能力、创建会话并开始预览,以及监听预览输出状态等步骤,并提供了代码示例。通过本文,读者可以掌握在HarmonyOS 5.0中使用ArkTS进行相机预览的基本方法。
16 6
|
1天前
|
编解码 开发工具 计算机视觉
鸿蒙5.0版开发:命令行工具(mediatool工具)
在HarmonyOS 5.0的开发中,命令行工具mediatool基于FFmpeg库,提供了丰富的媒体处理功能,如视频和音频的转码、封装格式转换、提取媒体信息等。本文详细介绍mediatool的功能和使用方法,并提供代码示例。
17 6
|
1天前
|
监控 Shell API
鸿蒙next版开发:使用HiChecker检测问题(ArkTS)
在HarmonyOS 5.0中,HiChecker是一个强大的工具,帮助开发者检测应用中的潜在问题,如耗时调用和资源泄露。本文详细介绍了如何在ArkTS中使用HiChecker,包括添加检测规则、触发检测和日志输出等步骤,并提供了示例代码。通过合理使用HiChecker,开发者可以提高应用的稳定性和性能。
16 6

热门文章

最新文章

下一篇
无影云桌面