项目github地址:https://github.com/CameloeAnthony/DatingBall
今天开始做自己的一个项目《约个球》,参考以前的项目,从零开始搭建。在整个项目的过程中会一步一步的搭建我们程序的框架。当然这个框架在以后的开发中是可以不断的用到的。不多说,开干。
项目开发环境:IntelliJ Idea
第1步:splashActivity也就是我们项目的启动的页面,也就是闪屏界面(可能会暂停三秒钟)。因为每一个项目中都会用到。所以我们在这里将它抽象出来,以后所有的类只需要继承这个类就可以了。
package com.nsu.library.app; import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; import android.widget.Toast; import com.nsu.library.R; import com.nsu.library.utils.NetUtil; /** * Create By Anthony on 2016/1/15 * 当前类注释:splashActivity的超类。完成跳转和加载数据的功能 * */ public class SplashActivity extends AbsFragmentActivity { private final short SPLASH_SHOW_SECONDS = 3; private Context mContext = this; private long mShowMainTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mShowMainTime = System.currentTimeMillis() + SPLASH_SHOW_SECONDS * 1000; //step 1 全屏 this.requestWindowFeature(Window.FEATURE_NO_TITLE); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //step 2 网络连接判断 if (!NetUtil.isConntected(AbsApplication.app())) { Toast.makeText(AbsApplication.app(), getResources().getText(R.string.please_connnect_network), Toast.LENGTH_SHORT).show(); } //step3 TODO 初始化数据 initData(); //step4 TODO 跳转到其他activity showView(); } protected void initData() { } private void showView() { AsyncTask showMainTask = new AsyncTask() { @Override protected Object doInBackground(Object[] params) { if (System.currentTimeMillis() < mShowMainTime) { try { long sleepTime = mShowMainTime - System.currentTimeMillis(); if (sleepTime > 0) { Thread.sleep(mShowMainTime - System.currentTimeMillis()); } } catch (InterruptedException e) { e.printStackTrace(); } } return null; } @Override protected void onPostExecute(Object o) { showMain(); finish(); } }; showMainTask.execute(); } protected void showMain() { ViewDisplayer.showMainActivity(this); } }分析:我们的activity会是一张全屏图片。在这里我们会做出网络的判断,也会加载数据和跳转到我们的MainActivity。
第2步:上面的SplashActivity继承自AbsFragmentActivity,这是我自定义的一个父类,继承自FrammentActivity(来自v4包):
package com.nsu.library.app; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.util.DisplayMetrics; import android.view.View; import android.widget.TextView; import com.nsu.library.R; import com.nsu.library.fragment.AbsFragment; /** * Create By Anthony on 2016/1/15 * 当前类注释:自定义的FragmentActivity,本项目中的所有的带Fragment的activity都将继承这个类 * 已实现:加载fragment, * 待实现:广播的注册和监听,服务的绑定,友盟数据初始化等公共代码 */ public abstract class AbsFragmentActivity extends FragmentActivity { public static final String EXTRA_TITLE = "title"; private DisplayMetrics metric; private Handler mHandler = new Handler(); private Fragment mFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); metric = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metric); mHandler.post(new Runnable() { @Override public void run() { mFragment = createFragment(); if (mFragment != null) { getSupportFragmentManager().beginTransaction().replace(getFragmentContainerID(), mFragment).commit(); if (mFragment instanceof AbsFragment) { ((AbsFragment) mFragment).notifyDisplay(); } } } }); } @Override protected void onDestroy() { super.onDestroy(); } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); TextView titleView = (TextView) findViewById(R.id.header_title); if (titleView != null) { setTitle(getIntent().getStringExtra(EXTRA_TITLE)); titleView.setText(getTitle()); } } /** 子类通过覆写这个方法传入的fragment将被这个类初始化 */ protected Fragment createFragment() { return null; } protected int getFragmentContainerID() { return 0; } public boolean hasBack() { return true; } public boolean hasHome() { return true; } public boolean hasSetting() { return true; } public float getmWidth() { return metric.widthPixels; } public float getmHeight() { return metric.heightPixels; } public float getScale() { return getResources().getDisplayMetrics().density; } public void onBtnBackClick(View view) { finish(); } }分析:在这个父类中我们定义Fragment的实现。以后就不需要每次复杂的写了。只需要调用createFragment和getFragmentContainerID两个方法。这里在后面的章节用到的时候会继续分析。
package com.nsu.library.app; import android.app.Application; import com.nsu.library.utils.log.LocalFileUncaughtExceptionHandler; /** * Create By Anthony on 2016/1/15 * 当前类注释:Application的子类,本项目中的Application将继承本类。 * 当前功能:单例模式,异常捕获,由子类实现的获取url */ public abstract class AbsApplication extends Application { private static AbsApplication sInstance; public static AbsApplication app(){ return sInstance; } @Override public void onCreate() { super.onCreate(); sInstance = this; Thread.setDefaultUncaughtExceptionHandler(new LocalFileUncaughtExceptionHandler(this, Thread.getDefaultUncaughtExceptionHandler())); } /***************** About URL ***********************/ public static enum SourceType{ JSON, XML,SOAP } abstract public String getApplicationConfigUrl(); abstract public SourceType getSourceType(); abstract public String getFirstClassUrl(); }第4步:在上面ViewDisplayer.showMainActivity(this);这个方法中我们就把MainActivity显示出来了,那么具体是怎么做到的呢?可以看看这个类:
package com.nsu.library.app; import android.app.Activity; import android.content.Context; import android.content.Intent; import com.nsu.library.constants.Constants; import com.nsu.library.utils.CommonUtils; import java.util.HashMap; /** * Create By Anthony on 2016/1/15 * 当前类注释:用于activity的展示,通过设置type,获取对应的activity,面向对象的抽象 * 键值对将在raw://type_activity_map_base文件中定义 * */ public class ViewDisplayer { private static HashMap<String, String> sTypeActivityNameMap = new HashMap<String, String>(); public static void initialize(Context context){ sTypeActivityNameMap.putAll(CommonUtils.simpleProperty2HashMap(context, Constants.BASE_TYPE_ACTIVITY_MAP_PATH)); sTypeActivityNameMap.putAll(CommonUtils.simpleProperty2HashMap(context, Constants.EXT_TYPE_ACTIVITY_MAP_PATH)); } public static void showFragmentActivity(Context context, String type){ //TODO } public static void showMainActivity(Context context){ showMainActivity(context,"1001"); } public static void showMainActivity(Context context, String type){ String activityName = sTypeActivityNameMap.get(type); if(activityName != null){ Intent intent = new Intent(); intent.setClassName(context, activityName); if(!(context instanceof Activity)){ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); } } }
里面的内容很简单:
1001=com.nsu.datingball.activity.MainActivity
也就是说1001对应我们的MainActivity。所以跳转页就实现了呢。
第五步: 好了,从我们的框架搭建完成了。开始我们自己项目中,我们将上面的包当做library,我们就可以写出自己的SplashAcrivity了,简化了许多步骤。
package com.nsu.datingball.activity; import android.os.Bundle; import com.nsu.datingball.R; /** * Create By Anthony on 2016/1/15 */ public class SplashActivity extends com.nsu.library.app.SplashActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_splash); } @Override protected void initData() { // super.initData(); //TODO 在这里异步加载数据哦 } @Override protected void showMain() { super.showMain(); } }