怎么样分析一个网站互联网品牌的快速推广
1.四大基本组件
activity
安卓中的基本组件之一,一个activity表示一个与用户进行交互的窗口。一般来说MainActivity就相当于Java项目中Main。
onCreate()方法,相当于public static void main(String args[]),照着写就完事了。
每个Activity固定的开头
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);}
注意每次从后台重新进入页面时,Activity都会重新被调用一次,也就是说onCreate()都会重新执行一遍。也就是说是新的代码。
onCreate()中不能拥有阻塞操作(死循环,socket.connect,readLine()),每次进入Activity中必须保证onCreate中得代码能够一次性执行完,这东西相当于初始化操作。
service
//开始Service
Intent intent=new Intent(this,MyService.class) //intent后面讲,MyService是继承Service的自定义类
startService(intent);MyService内部执行过程:1.onCreate(),只用第一次start会调用 2.onStartCommand(变量忘了),每次start都会调用,代码写在这里。
//结束
stopService(intent); MyService:直接执行onDestroyed里面的函数
2.View组件
用来绘制图像的画板,相当于Swing中的Frame和JPanel合体版。View只是一个画板
view的一些基本方法
*boolean onKeyDown(int keyCode , KeyEventevent);用户在该组件上按下时触发的
*boolean onKeyLongPress(int keyCode ,keyEvent event);用户在该组件上长按时触发的
*boolean onkeyShorcut(int keyCode ,keyEvent event);当一个键盘快捷键事件发生时触发该方法
*boolean onkeyUp(int keyCode , keyEventevent);用户松开按键的时候触发的事件
*boolean onTouchEvent(MotionEvent event);用户在该组件上触发触摸屏时触发该方法
*boolean onTrackballEvent(MotionEventevent);用户在该组件商触发轨迹球时触发该方法
setContentView()
setContentView()只能在Activity中的onCreate()中进行,不能新建一条线程,不然直接暴毙,会启动不了。我也不知道是什么原因。反正不能新建线程create。
3.R类
android studio在编译时会自动生成一个R类。R类可以调用res文件夹下的所有资源,一般是指res/layout
例如,我在res/layout中定义了一个button组件,他的id是button1
则可以通过如下代码获得组件,和Javascript很像
findViewById(R.id.button1)
4.前端
布局
布局方面和Web开发很像,通过XML进行组件的布局,只不过没有CSS的存在
5.多线程
Handler类
多线程中,每隔线程的消息都需要发送到Handler类,Handler集中处理。大概是这样
主线程和子线程
在一个Activity中能够更新UI的只有主线程(就是onCreate那个),其他人工新建的子线程都不能直接操作UI界面,同时主线程是绝对不能出现阻塞操作,例如在onCreate里面执行Thread.sleep(),同步锁之类的都是绝对不会被允许的,所以耗时的操作只能新建一条线程来实现。例如网络连接,网络请求都要放在新建的子线程中去搞。setContentView只能在主线程中实现,子线程中无法使用
通过Handler去操作主线程
子线程如果想要更新UI界面必须通过Handler向主线程发出请求,然后更新UI。简单的来说Handler就是主线程和子线程的通信媒介,使得子线程也能间接的执行更新UI的操作,当然Handler也可以用于子线程之间
Android异步通信:这是一份Handler消息传递机制的使用教程 - 简书
核心的handler类代码,在handleMessage中执行更新UI的操作,具体查看上述链接
class mHandle extends Handler{@Overridepublic void handleMessage(Message msg){//重写这部分代码用来更新UI}
}
需要注意的是,一条线程只能使用Handler一次,也就是说每条线程只有一次通过Handler向主线程发起更新请求的机会,如果要多次发出更新UI的线程建议在子线程里面再新建一条线程
6.绘画
安卓的绘画需要在View模块中进行。基本思路是在View里面新建一个线程Thread进行绘画的动作更新,然后再View里面的surfaceCreated()中调用线程。
public void run(){draw();
}public void surfaceCreated(){new Thread(this).start;
}
与Swing开发的区别在于,这个View类相当于Frame和Panel的混合体。画的过程必须是新建线程,不能再主线程中画。
SurfaceHolder可以视作是用来管理SurfaceView的接口
获得画布
myCanvas=mySurfaceHolder.lockCanvas();
图片重复或抖动的现象
canvas画图的基本原理应该是覆盖,而不是清空。如果你的图片太小,没办法覆盖整个屏幕的话,此时如果你循环绘制同样的图片且每次绘制都偏移一点,应该会出现重复或抖动的现象。
在飞机大作战中,会出现抖动的现象,如图
大概率是因为图片太小了,没办法覆盖整个屏幕,所以导致重叠。解决方法,用canvas绘画前,先清空之前的画布。或是找一个特别大的图片覆盖整个屏幕。
或是再绘画前先使用canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)来清空之前的画布
提供一个图片缩放的算法
SurfaceView的执行过程
1.进入程序调用surfaceCreated()
2.调用surfaceChanged(),改变屏幕的长和宽
3.推出程序,例如点击home或返回,或是直接刷新内存时,都会调用surfaceDestroyed()
Bitmap
Bitmap用来加载图片,相当于Java中的BufferImage,方法都是类似的。
//声明图片的变量
private Bitmap imgae;//获取图片
image=BitmapFactory.decodeResource(getResource(),R.drawable.image);
7.音视频MediaPlayer
Android内置多媒体播放器,MediaPlayer,能够播放音视频。
不过要注意的是MediaPlayer是一个有限状态机,所以要在合适的状态调用合适的方法,否则会出现一堆的报错。有一种比较简单的粗暴但性能很低的调用方法时,每次播放音视频前都实例化MediaPlayer一次,在用start播放音视频。
示例
//初始化播放器
MediaPlayer player=MediaPlayer.create(this,R.raw.mymusic);//是否循环播放,默认是不循环
player.setLooping(false);//播放音乐
player.start();
这东西不能用在View
SoundPool
SoundPool一般是用来播放特效音乐的,例如游戏当中的爆炸声,子弹射击声音。之所以这样晚会是因为如果都用mediaPlayer播放会很卡,mediaPlayer是一个文件接一个文件的播放的,每次只能播放一个音乐,而SoundPool在播放时会单独设置线程,支持同时播放多个音乐。
使用步骤如下
1.初始化
8.网络开发
网络开发需要两部分程序(即两个project),一个服务器,一个客户端。
服务器启动后不断的监听客户端,以做出响应,做出响应新建一条线程来处理响应,防止监听中断。
socket:网络上的搬运工
服务器和客户端通过socket进行信息的交互,客户端通过socket发出信息,服务器通过socket接收信息。scoket这个类就是一个搬运工。
socket中的端口port的作用是为了让服务器识别客户端,每一个客户端都有一个单独的port,这个port相当于一个ID。例如飞机大作战联网中,用户A的port是1,B的是2;则在服务器要建立两个socket分别对应A和B
对于同一个端口多次建立连接时,每次连接都是不同客户,所以没连接一次要单独开一条请求线程处理请求,这样就能实现Socket一对多的通信。
ServerSocket serverSocket=new ServerSocket(9999);//监听端口号9999int count=0;
while(true){count++;Socket socket=serverSocket.accept();System.out.println("第"+count+"个客户");new ServiceThread().start();//处理客户请求的多线程,自己去实现
}
服务器
服务器是一个信号中转站,用来实现不同的客户之间的信号交互,或是服务器与用户的信号交互。服务器创建后时刻监听客户的请求,根据用户的请求做出具体的响应。关闭的服务器与用户连接的逻辑代码建立在服务器内,客户端中存在的永远都是请求而不是具体的处理逻辑。
BufferReader
网络中数据的交互需要通过bufferreader和bufferwriter处理流来进行IO操作
需要注意的是BufferReader中的readline()返回一个字符串,而且只会返回一次,返回后就没了,这个其实和在控制台用BufferReader进行输入操作是一样的,控制台中输入一次数据就是一次readline(),程序通过readline()把数据传到变量中,下一次输入就是下一个readline()。在网络开发中也一样。一次请求,数据发送端通过BufferWriter输出一个数据,接收方用BufferReader的readline()接受数据据并读出。读完后就没了,再次readline()直接为空。
使用readLine()后,如果readLine()没有读到值,不会输出null,而是进入一个阻塞状态,一致等待有东西输入,就像在控制台那样,这样就实现了服务器对客户端请求的时刻监听。
socket的连接一旦关闭后,那么对应的InputStream会立刻变为空,也就是说readLine()这时候读的肯定是空。socket重新连接时,会先关闭再连接。
BufferReader in=new BufferReader(new InputStreamReader(socket.getInputStream))//之后正常的用 in.readLine()就可以读数据了
PrintWriter
PrintWriter用来输出数据,可以理解为发射
PrintWriter writer=new PrintWriter(new BufferWriter(new OutputWriter(socket.getOutputStreamWriter)))//之后用 writer.println()正常的输出就好
多线程
服务器对一个客户端的的监听是一条线程,一个客户端对应一条线程,别把两个客户放到同一个线程中,这样耦合程度太高了
客户端对服务器的响应和请求也是一个线程,这样实现数据传输和逻辑功能的解耦,主线程从子线程中拿数据用就好。
无论是客户端请求连接还是处理连接,或是服务器端监听客户端时刻响应连接都必须要使用多线程,不然socket.connect()会报错
基本思想是,在请求连接或是响应数据传送时都要使用多线程
以飞机大作战为例
服务器:监听玩家得得分情况和传送对手得分是一条单独得线程
客户端:建立连接需要一条请求连接线程
响应数据传送(传送己方得分,接受对方得分)需要一条线程
服务器端
while(true){Socket socket=SocketServer.accept()//等待客户端发起连接,如果没接收到就一直等new ServiceThread().start();//开启服务线程
}
客户端
//连接线程
class ConnectThread extends Thread{public void run(){(1) 方法一 Socket socket=new Socket("IP 地址",端口号);//端口号相当于客户得ID,随便取名(2) 方法二 Socket socket=new Socket();socket.connect(new InetSocketAddress("IP",端口),连接时间界限);//连接超过时间界限会报错}
JSON的使用
1.客户端端
直接调用JSONObject就好,这个JSONObject可以完全当成javascript里面的对象去弄就好。
//声明JSONObject
JSONObject jsonObject=new JSONObject();//给json中增加键值对或是改变json的键值对的值
jsonObject.put(key,value);
2.需要引入JSONObject的相关依赖
GitHub - joytom/json_all: java使用json所需要的全部jar包
这个JSONObject和Android自带的JSONObject可以看作是两个东西,大部分地方一样,但在细节层面上有所不同。
//其他类转为JSON
jsonObejct=JSONObject.fromObject(Object);//JSON的put方法只能引入键值对
jsonObject.put(key,value);//更改同一个key的value不能使用put方法,只能先转化位Map再通过更改Map后再次转为Json
//这里需要使用迭代器
Map<String,Object> map=new HashMap<>();
for(Iterator<String> it=jsonObject.keys();it.hasNext();){String key=it.next;switch(key){case "key1":map.put(key,value1);break;case "key2":map.put(key,value2);break;....default:}jsonObject=JSONObject.fromObject(map);
}
Socket和输出输出流的创建
个人建议请求连接和监听程序放在同一个.java文件(或是说同一个类)当中实现,尽量避免出现需要使用socket传参。输出流和输入流的建立需要在connect后直接建立,不然会暴毙,会出现报错。报错的原因大概率是因为建立input和output是socket还是空,所以没办法建立连接。所以使用socket时尽可能的保证socket.connect后直接创建输入流和输出流,而且必须要先connect在创建输入和输出流,不然会创建失败。这个说明输入输出流和connect如果在两条线程里面执行的话,必须保证connect的结束后才会启动输入输出流的创建线程,同时输入输出流用到的socket一定是已经connect的socket。
简单的来说创建输入输出流要保证如下的顺序
socket.connect(new InetSocketAddress(Ip,端口),5000)PrintWriter writer=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream)));
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
建议先创建输出流再创建输入流养成良好的习惯
IP地址查询
1.局域网IP
再命令行中输入ipconfig即可显示出本机的局域网下的IP地址
以太网:有线局域网连接标准,如果电脑不接网线,这东西默认是什么都没有。里面的IP都是有线局域网下的IP,例如192.168.xx.xx
无线局域网 wlan:wifi连接下本机的局域网IP,只需要关注IPv4就好,这个IPv4就是在当前wifi下你这台电脑的IP地址。一般情况下如果要实现同一个wifi下的网络通信,客户端用这个IPv4去连接服务器。注意这里的IP是指服务器的IP。
2.公网的IP
在百度上面输入IP就可以查到本机的公网IP了。这个IP是全球唯一,由运营商分配的,你不用管,也管不了。
部分内网可能有权限设置,此时用内网的IP可能无法进行网络通信(例如校园网)。这时会出现android.system.ErrnoException: isConnected failed: EHOSTUNREACH (No route to host)错误。
解决方法:用手机开热点,同时连接服务器和客户端
9.样式拼接
recycleview和listview