安卓微博客户端 第二天 系统主框架的搭建

  从上次更博到今天过了三天了,并不是因为偷懒了,而是这一课的内容对于基础较差的我来说信息量有点过于大了,隔了这么久才勉勉强强把它吃掉。那么废话不多说,直接进入今天的内容吧。

  首先先看一下到目前为止的UI效果图:

   

  除了下面多了一个“Welcome to Sina”的TextView,也没什么变化呀。哈哈,那你就错了,上次我们这两个按钮是点不动的,这次都有各自的功能了,先输入用户名和密码点下登录试试。

  嗯,各位没有看错,就是将下面的TextView内容改变了。哈哈,可能有人要骂娘了,这不是小学生都会改的吗。嗯,的确,单纯的想改掉它很容易,不过我们这次的主题是主框架的搭建,这只是往框架里面填充了一点内容的结果,整个过程还是费了一点周折的,所以还请大家稍安勿喷。我们继续看UI

  这是点旁边Register的按钮后的结果

  这个Activity中,点击取消按钮会返回到上一个Activity中,还没有给注册按钮绑定监听器,不过我们的重点是搭建框架搭建框架搭建框架,框架搭建好了,往里面添加功能很容易的。好了,UI展示就到这里,下面开始讲解丑陋的UI背后的框架是怎么搭建的。

====================分割线====================

  这就是整个主框架的工作流程了,多了几个名词,service、handle、线程。这些对于老鸟来说应该都听出老茧了吧,不过对于像我一样刚接触安卓的小白来说还是很陌生的,嗯,下面放两个链接来给小白涨涨姿势。service、handle这两个东西很重要,不懂他们我们的项目就没有办法继续进行下去了。嗯,先把这张图看上三分钟

  http://www.360doc.com/content/14/0415/18/2793098_369238276.shtml

  http://blog.sina.com.cn/s/blog_77c6324101016jp8.html

  首先是我们的主Activit,由于在后期要对我们的UI进行刷新,所以我们Activity的定义方式也高大上了许多

public class LoginActivity extends AppCompatActivity implements IWeiboActivity

  IWeiboActivity接口中定义了操作UI的方法  

public interface IWeiboActivity {

//    初始化数据
    void init();

//    刷新UI
    void refresh(Object...params);
}

  LoginActivity的入口还是onCreate方法

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);

        loginButton = (Button)findViewById(R.id.LoginButton);
        registerButton = (Button)findViewById(R.id.RegisrerButton);

        Intent intent = new Intent(this, MainService.class);

        startService(intent);

        ButtonClickListener buttonClickListener = new ButtonClickListener();
        loginButton.setOnClickListener(buttonClickListener);
        registerButton.setOnClickListener(buttonClickListener);

        MainService.addActivity(this);
    }

  嗯,开始定义了几个Button,这些不是重点,后面再讲。重点是我红色高亮的代码。我们在这里使用Intent启动了一个Service,也就是流程图中的MainService。安卓中Activity只负责跟用户卖萌耍怪,背后的脏活累活都是Service在干。同样先看看MainService的定义方式吧

public class MainService extends Service implements Runnable 

  这里我们的MainService还继承了Runnable接口,但是并不能说Service是线程,它和线程半毛钱关系都没有。我上面分享的文章里面强调过了,这里在强调一遍,Service不是线程!Service不是线程!Service不是线程!好,我们继续。

  同样的,Service的主入口还是onCreate方法

public void onCreate() {
        super.onCreate();
        isRun = true;
        Thread thread = new Thread(this);
        thread.start();
    }

  由于我们的MainService继承了Runnable接口,所以这里可以作为参数传递给Thread构造函数。这里新开了一个线程,我们再看看run方法

public void run() {
        Task task = null;
        while (isRun)
        {
            if(!tasks.isEmpty())
            {
//                队列不为空则赋给task并从队列中移除
                task = tasks.poll();
                if(task != null)
                {
//                task不为空就执行task,以后会实现
                    doTask(task);
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

  这个线程的任务就是时刻检测当前有没有任务,有则去执行,没有就继续循环。其中tasks是一个任务队列,定义方式如下

private static Queue<Task> tasks = new LinkedList<Task>();

  队列嘛,先进先出,数据结构都学过的,不懂的小伙伴们上网搜一搜就好了。<>这个尖括号中的东西叫做泛型,也就是这个队列中每一个元素的类型,下面是Task类的内容

  

public class Task {
//  任务Id
    private int taskId;

//    微博登录
    public static final int WEIBO_LOGIN = 1;
//    微博注册
    public static final int WEIBO_REGISTER = 2;

//    参数
    private Map<String, Object>taskParams;

    public void setTaskId(int taskId) {
        this.taskId = taskId;
    }

    public void setTaskParams(Map<String, Object> taskParams) {
        this.taskParams = taskParams;
    }

    public int getTaskId() {
        return taskId;
    }

    public Map<String, Object> getTaskParams() {
        return taskParams;
    }
    public Task(int taskId, Map<String, Object>taskParams)
    {
        this.taskId = taskId;
        this.taskParams = taskParams;
    }

}

  别看这个Task内容多,其实就定义了一个任务ID"TaskId"和参数键值对taskParams还有一些静态常量,剩下的都是构造函数和set、get方法。

  那我们检测任务的工作到这里也做完了,那么谁来给我们的Service分配任务呢?其实想想就能得出答案:app是为用户服务的,所以任务肯定也是人来下达,而app中和人交互的又是UI,所以给Service下达任务的肯定是UI啦。看我们的流程图也能得出任务是UI给出的这个结论。现在又返回到LoginActivity看看他是如何下达任务的。

  在LoginActivity中定义了几个按钮,绑定了监听器,监听器内容如下

 private class ButtonClickListener implements View.OnClickListener
    {
        @Override
        public void onClick(View v) {
            Task task = null;

            switch (v.getId())
            {
                case R.id.LoginButton:
                    task = new Task(Task.WEIBO_LOGIN, null);
                    MainService.newTask(task);
                    break;

                case R.id.RegisrerButton:
                    task = new Task(Task.WEIBO_REGISTER, null);
                    MainService.newTask(task);
                    break;

                default:
                    break;
            }
        }
    }

  可以看到,在case中生成了一个Task对象,并使用MainService中的静态方法将它添加到了任务队列中

//    添加任务到任务队列中
    public static void newTask(Task t)
    {
        tasks.add(t);
    }

  嗯,这里因为我们的tasks成员也是静态的,否则是不能这么用的(静态方法中用到的成员变量必须都是静态的)

  这边将任务添加到消息队列,还记得之前在MainService中开的那个线程吗?它检测到任务队列中有了新的任务,就会调用doTask方法去执行。 

private void doTask(Task t)
    {
        Message msg = handler.obtainMessage();
        msg.what = t.getTaskId();

        switch (t.getTaskId())
        {
            case Task.WEIBO_LOGIN:
                System.out.println("doTask >>>>>>  用户登录任务");
                msg.obj = "正在登录....";
            break;

            case Task.WEIBO_REGISTER:
                System.out.println("doTask >>>>>>  用户注册任务");
                break;

            default:
                break;
        }
        handler.sendMessage(msg);
    }

  在doTask中先用handler生成了一个消息实例,将Task的Id放入msg中,又根据TaskId对任务进行进一步细分,最后将消息发送给handler。注意,这个doTask是在thread线程中的,handler

则是在MainService中定义的

class Myhandler extends Handler
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            IWeiboActivity activity = null;
            switch (msg.what)
            {
                case Task.WEIBO_LOGIN:
//                    更新UI

                    activity = (IWeiboActivity)getActivityByName("LoginActivity");
                    activity.refresh(msg.what, msg.obj);
                    break;
//                    跳转到注册页面
                case Task.WEIBO_REGISTER:
                    activity = (IWeiboActivity)getActivityByName("LoginActivity");
                    activity.refresh(msg.what);
                    break;

                default:
                    break;
            }
        }
    }

    Myhandler handler = new Myhandler();

  那么问题来了,为什么明明可以在doTask中对UI进行改变,为什么又要费一番周折把它写到handleMessage函数中?答案就是:安卓不允许除了Activity中的主线程以外的线程来改变UI!还想表达的一个意思就是Service中的代码其实也是启动它的Activity的主线程中的。所以,我们不能够在doTask中刷新UI。

  后面的工作就简单了,获取要改变的activity,并调用对应的refresh。这里得到的activity必须继承过IWeiboActivity接口,因为refresh等方法是在IWeiboActivity这个接口中定义的。里面用到了一个getActivityByName的方法

private Activity getActivityByName(String name)
    {
        if(!appActivities.isEmpty())
        {
            for (Activity activity : appActivities)
            {
                if(activity != null)
                {
                    if(activity.getClass().getName().indexOf(name) > 0)
                    {
                        System.out.println(activity.getClass().getName());
                        return activity;
                    }
                }
            }
        }
        return null;
    }

  appActivities是一个ArrayList类型的变量,也是一种组织数据的类型,定义如下

private static <Activity> appActivities = new ArrayList<Activity>();

  和Queue同理,appActivities中的元素都是Activity类型的。直到这里,我们在MainService中要做的工作也就完成了。

  最后还有点小尾巴,就是Activity中refresh函数的实现,这部分就很简单了,由于不同的任务传递的参数不同,所以这里使用了变参函数  

public void refresh(Object... paramas) {

        int choose = Integer.parseInt(paramas[0].toString());

        switch (choose)
        {
            case Task.WEIBO_LOGIN:
                Log.d("MainService", paramas[1].toString());
                textView = (TextView)findViewById(R.id.textId);
                textView.setText(paramas[1].toString());
                break;
            case Task.WEIBO_REGISTER:
                Intent intent = new Intent(this, RegisterActivity.class);
                startActivity(intent);
            default:
                break;
        }

    }

  这就是整个主框架的设计。没错,想要单纯的改掉UI很容易,但是那只是我们模拟登录,如果真正实现登录就不会这么简单。并且有了框架我们再想加入别的功能就会特别容易,定义一个task实例添加到任务队列中,并实现具体的功能就好了,这样整个项目就很具有逻辑性,便于管理和优化。

  这次的笔记就做到这里,总结一下get到的新技能:service、handler的使用,java中的foreach语句(轻喷,Java基础不扎实),还有返回上一级activity的finish方法。由于信息量对我来说是有一点大,这次讲的逻辑也挺混乱的,欢迎各位拍砖。

  项目源码下载链接:http://files.cnblogs.com/files/51qianrushi/Iweibo.zip

  这次的内容就这么多,下次再见。转载请通知本人或注明出处

时间: 2024-10-13 11:41:38

安卓微博客户端 第二天 系统主框架的搭建的相关文章

三:新浪微博--主框架的搭建

一:主框架分析: 1:主框架的效果图如下:底部有一个tabBar,点击tabBar按钮切换首页,信息,发现 和我几个界面.则考虑将UITabBarController作为窗口的根视图控制器,所以新建类继承UITabBarController,用来封装主框架 : 2:封装根视图控制器UITabBarController的代码: 1 #import "HMTabBarViewController.h" 2 #import "HMHomeViewController.h"

.net 中主框架的搭建(2种方式)

第一种:windows办公界面 主要步骤如下: 1)引入ligerui库 复制代码到index界面修改相关路径 2) 选择布局 进行流失布局 <title></title> <link href="/Content/ligerui/Source/lib/ligerUI/skins/Aqua/css/ligerui-all.css" rel="stylesheet" /> <script src="/Content/

FragmentTabHost+Fragment搭建应用主框架

一.主界面Activity代码 public class MainActivity extends FragmentActivity{ //定义FragmentTabHost对象 private FragmentTabHost mTabHost; //定义一个布局填充器 private LayoutInflater layoutInflater; //定义数组来存放Fragment界面 private Class<?> fragmentArray[] = {HomeFragment.class

S2SH框架新手搭建详细过程

S2SH框架整合新手学习总结 第一篇:S2SH框架新手搭建准备工作只都需要导入那些文件 第二篇:S2SH框架新手搭建详细过程 版本信息:Struts2.3+Hibernate4.3.6+Spring4.2.0 三个框架,是需要整合起来可以使用的: 首先是导入必要的包,具体导入哪些文件可以参考我的第一篇博文 (1)导入Struts2包 (2)配置Struts2 新建一个struts.xml文件,默认的位置是项目的src根目录,与你的action等等包是同级的 <?xml version="1

基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): 1.实现基本通信框架,包括对游戏的需求分析.设计及开发环境和通信框架的搭建: 2.实现网络底层操作,包括创建线程池.序列化网络包等: 3.实战演练,实现类似于CS反恐精英的3D对战网络游戏: 技术要点:C++面向对象思想.网络编程.Qt界面开发.Qt控件知识.Boost智能指针.STL算法.STL.

作业七:B站安卓手机客户端体验

上次作业中提到初入B站的经历.体会.以及B站首页问题衍生的对目前web网页的看法.随着几天的慢慢深入体验, 在B站上发现了越来越多的感兴趣的UP主和UP主们的视频作品.我第一个关注的是暴走漫画的敖厂长,刚看到就关注了 敖厂长,毕竟暴漫粉丝.看了几期敖厂长的游戏解说视频后不得不佩服敖厂长的口才.下面的“超级马里奥2”就是经 典之作.“[敖厂长]超级玛丽扭曲的黑历史” 接着就遇到了用琵琶弹奏170加速版千本樱的大神 以及有Epic史诗工作坊出品的MC游戏中还原四分之一的圆明园的场景图,简直就是神作!

Android新浪微博client(一)——主框架搭建

原文出自:方杰| http://fangjie.sinaapp.com/?p=62 转载请注明出处 该项目代码已经放到github:https://github.com/JayFang1993/SinaWeibo 提前声明的是,我是依照Ivan的这套教程学下来的. 首先,对于不论什么应用我们都须要建立一套消息处理机制,就是当用户在UI界面上点击了什么.你应该做出什么样的处理,处理完毕之后又要将结果 反馈给用户.显示在UI界面上.简而言之:主框架在这里主要是搭建起一个异步消息处理机制,UI线程中发

iOS 类似简单的第三方微博客户端,可进行登录微博浏览相关信息

Demo地址:https://github.com/ChenNan-FRAM/Fenvo (如果你觉得有用麻烦star一下感激不尽) Fenvo Objective-C, iOS 类似简单的第三方微博客户端,可进行登录微博浏览相关信息.在这个过程我是遇到很多的问题,但是大部分都顺利解决了,相信如果你的项目有类似的地方我的项目里面也能够给你提供一定的帮助,如果需要,可以给我留言或者在Github上联系我. UI简陋,暂未完善.有UI大师指点就最好了. 这个应用我是从开始学后为了实践自己的能力一直在

安卓22学分绩点系统(app+server)

一.技术实现: 开发语言: javaweb+安卓, 模式:客户端app+服务端web,数据库 : mysql. 论文字数:1万左右. 二.功能实现: 三.系统截图 转载于我帮你毕业设计需要详细信息可以联系 Q 2786639042或者去网站www.hongtaibysj.com查阅