portlet

As we’ve seen previously, Portlet is conceptually very similar to Servlet as they can only operate within a container. Both Servlet and Portlet have an obligations that their design must satisfy to allow them interact with their containers.

如前所述,Portlet在概念上与Servlet非常相似,因为它们只能在容器内运行。 Servlet和Portlet都有其设计必须满足的义务,以允许它们与容器进行交互。

As you should implement doGet(), doPost(), doDelete(), etc, you must also implement the Portlet’s specific methods like doView(), doHelp(), doEdit(), etc.

在实现doGet()doPost()doDelete()等时,还必须实现Portlet的特定方法,如doView()doHelp()doEdit()等。

Let’s firstly starting by developing our first Portlet by implementing the Portlet interface than using of GenericPortlet and highlights the most important things.

首先,通过实现Portlet接口而不是使用GenericPortlet来开发我们的第一个Portlet,并重点介绍最重要的事情。

Following sections would help cover these concepts:

以下各节将帮助涵盖这些概念:

  • Implementing Portlet Interface.实现Portlet接口。
  • Break down of Portlet’s Lifecycle.分解Portlet的生命周期。
  • Portlet Creation Stage.Portlet创建阶段。
  • Request Handling Stage.请求处理阶段。
  • Portlet Destruction Stage.Portlet销毁阶段。
  • Threading Issues.线程问题。
  • Summary.摘要。

实现Portlet接口 (Implementing Portlet Interface)

Generally, you can develop your Portlet by extending the GenericPortlet, any class that’s extending the GenericPortlet or by implementing the Portlet interface.

一般情况下,你可以通过扩展开发您的portlet GenericPortlet ,这就是扩展任何类GenericPortlet或实现Portlet接口。

package com.journaldev.portlet;import java.io.IOException;import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;public class LifecyclePortlet implements Portlet {private static int renderCount = 0;private static int actionCount = 0;private static int initCount = 0;@Overridepublic void init(PortletConfig config) throws PortletException {initCount++;}@Overridepublic void processAction(ActionRequest request, ActionResponse response)throws PortletException, IOException {synchronized(this){actionCount++;}}@Overridepublic void render(RenderRequest request, RenderResponse response)throws PortletException, IOException {synchronized(this){renderCount++;}response.getWriter().print("<form action="+response.createActionURL()+">"+ "<p> The number of initiated Portlets by the container is :: "+initCount+"</p>"+ "<p> The number of processed actions by the container is :: "+actionCount+"</p>"+ "<p> The number of achieved render by the container is :: "+renderCount+"</p>"+"<input value='Submit' type='submit'/><br/>"+ "<a href='"+response.createRenderURL()+"'>Render Again</a>"+ "</form>");}@Overridepublic void destroy() {initCount--;System.out.println("The number of Portlets get deployed :: "+initCount);}
}
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.journaldev</groupId><artifactId>LifecyclePortlet</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>LifecyclePortlet</name><url>https://maven.apache.org</url><properties><deployFolder>D:/Apache Pluto/pluto-2.0.3/webapps</deployFolder></properties><dependencies><!-- Java Portlet Specification V2.0 --><dependency><groupId>org.apache.portals</groupId><artifactId>portlet-api_2.0_spec</artifactId><version>1.0</version><scope>provided</scope></dependency></dependencies><build><plugins><!-- bind 'pluto2:assemble' goal to 'process-resources' lifecycle --><!-- This plugin will read your portlet.xml and web.xml and injects requiredlines --><plugin><groupId>org.apache.portals.pluto</groupId><artifactId>maven-pluto-plugin</artifactId><version>2.1.0-M3</version><executions><execution><phase>generate-resources</phase><goals><goal>assemble</goal></goals></execution></executions></plugin><!-- configure maven-war-plugin to use updated web.xml --><!-- This plugin will make sure your WAR will contain the updated web.xml --><plugin><artifactId>maven-war-plugin</artifactId><version>2.1.1</version><configuration><webXml>${project.build.directory}/pluto-resources/web.xml</webXml></configuration></plugin><plugin><artifactId>maven-antrun-plugin</artifactId><executions><execution><id>copy</id><phase>integration-test</phase><configuration><tasks><copy file="target/${project.build.finalName}.war" tofile="${deployFolder}/${project.build.finalName}.war" /></tasks></configuration><goals><goal>run</goal></goals></execution><execution><id>delete</id><phase>clean</phase><configuration><tasks><delete file="${deployFolder}/${project.build.finalName}.war" /><delete dir="${deployFolder}/${project.build.finalName}" /></tasks><detail>true</detail></configuration><goals><goal>run</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.7</source><target>1.7</target></configuration></plugin></plugins><finalName>${project.artifactId}</finalName></build>
</project>

portlet.xml

portlet.xml

<?xml version="1.0" encoding="UTF-8"?><portlet-app xmlns="https://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"version="1.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsdhttps://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"><portlet><description>First Portlet</description><portlet-name>PortletOne</portlet-name><display-name>First Portlet</display-name><portlet-class>com.journaldev.portlet.LifecyclePortlet</portlet-class><supports><mime-type>text/html</mime-type><portlet-mode>VIEW</portlet-mode></supports><portlet-info><title>Lifecycle Portlet</title><short-title>Lifecycle Portlet</short-title><keywords>Lifecycle</keywords></portlet-info></portlet>    <portlet><description>Second Portlet</description><portlet-name>PortletTwo</portlet-name><display-name>Second Portlet</display-name><portlet-class>com.journaldev.portlet.LifecyclePortlet</portlet-class><supports><mime-type>text/html</mime-type><portlet-mode>VIEW</portlet-mode></supports><portlet-info><title>Lifecycle Portlet</title><short-title>Lifecycle Portlet</short-title><keywords>Lifecycle</keywords></portlet-info></portlet>
</portlet-app>

Here’s detailed explanation for code listed above:

这是上面列出的代码的详细说明:

  • Executing mvn clean integration-test package will get your project to be packaged and deployed against your Apache Pluto.执行mvn clean integration-test package将使您的项目被打包并针对Apache Pluto进行部署。
  • LifecyclePortlet has implemented the Portal interface, as it’s obvious all contract methods must be implemented.LifecyclePortlet已经实现了Portal接口,因为显然必须实现所有合同方法。
  • Portlet deployment descriptor portlet.xml has defined two different Portlets that are referenced the same Portlet class. Such that deployment is acceptable as it can be deployed any number of Portlets that refer the same Portlet class with different names. It could also be to deploy two Portlets have the same name but make sure you are got deployed them into two different contexts.Portlet部署描述符portlet.xml已经定义了两个引用相同Portlet类的不同Portlet。 这样的部署是可以接受的,因为可以部署使用相同名称引用相同Portlet类的任意数量的Portlet。 也可能是部署两个具有相同名称的Portlet,但要确保将它们部署到两个不同的上下文中。
  • When it create a Portlet by implementing Portlet interface, render(), processAction(), init(), destroy() should be overridden.当通过实现Portlet接口来创建Portlet时,应该重写render()processAction()init()destroy()
  • When the Portlet get deployed, the Portlet container would call the init() at the initialization phase.当部署Portlet时,Portlet容器将在初始化阶段调用init()
  • When the client has activated submit button that’s displayed at the Portlet, the Portlet container has received such that call and it’s called processAction() method by its turn.当客户机激活了Portlet上显示的Submit按钮时,Portlet容器已收到这样的调用,并且该调用又被称为processAction()方法。
  • When the client has activated the renderAgain link that’s rendered at the Portlet, the Portlet container has received such that call and it’s called render() method by its turn.当客户端激活了在Portlet上渲染的renderAgain链接时,Portlet容器已收到这样的调用,并且该调用又被称为render()方法。
  • If you’ve execute mvn clean against LifecyclePortlet project, you should notice that your WAR file and its un-packaged format (WAR folder) are deleted. Deletion the context will cause that your defined Portlets to be destroyed.如果已对LifecyclePortlet项目执行mvn clean ,则应注意,您的WAR文件及其未打包的格式(WAR文件夹)已删除。 删除上下文将导致您定义的Portlet被销毁。
  • To get your WAR file removed a new execution has been added at the maven-antrun-plugin.为了删除您的WAR文件,在maven-antrun-plugin添加了新的执行。

Now, let’s see what might happen if we have removed the deployed WAR and its unpackaged folder. Absolutely, removing your deployed application will get the context listener to be invoked as it will destroy the all resources that are deployed including these defined Portlets inside the portlet.xml file.

现在,让我们看看如果删除了已部署的WAR及其未打包的文件夹会发生什么。 绝对,删除已部署的应用程序将使上下文侦听器被调用,因为它将破坏已部署的所有资源,包括portlet.xml文件中已定义的Portlet。

As we have two deployed Portlets (PortletOne, PortletTwo), we print out the numbers of remaining Portlets inside the destroy() method. This method has invoked similar to Servlet’s destroy() method that’s invoked once the contained project has undeployed.

因为我们有两个已部署的Portlet(PortletOne,PortletTwo),所以我们打印出destroy()方法中剩余Portlet的数量。 此方法的调用类似于Servlet的destroy()方法,该方法在取消包含项目后立即调用。

If you’ve looked deeply at the console messages, you should notice the Portlet context /LifecyclePortlet-0.0.1-SNAPSHOT be removed. Usually, the concepts of undeploy and context removal are used interchangeably.

如果您已深入查看控制台消息,则应注意已删除了Portlet上下文/LifecyclePortlet-0.0.1-SNAPSHOT 。 通常,取消部署和上下文删除的概念可以互换使用。

Portlet生命周期 (Portlet Lifecycle)

As simple as that, we can break down the Portlet lifecycle into these below stages:

如此简单,我们可以将Portlet生命周期分解为以下几个阶段:

  • Creation of Portlet.创建Portlet。
  • Processing of a number of user requests (or it might be none).处理多个用户请求(或者可能没有)。
  • Removal and garbage collection of the Portlet.Portlet的除去和垃圾回收。

Let’s delve thoroughly to discuss these stages deeply.

让我们深入研究这些阶段。

Portlet创建阶段 (Portlet Creation Stage)

The creation of the Portlet is the most expensive and complicated phase among mentioned phases as it consists of three distinct steps: loading the classes, invoking the constructors and initializing the Portlet.

Portlet的创建是上述阶段中最昂贵,最复杂的阶段,因为它包含三个不同的步骤:加载类,调用构造函数和初始化Portlet。

Generally, the container is able to load the classes required by the Portlet before constructor invocation. The Portlet that’s loaded is considered as a minor part in compare with the whole application that might contain a lot of classes and libraries. As such the specification demands that the loading of the Portlet class must be done using the same classloader as the rest of the Portlet application that the loaded Portlet referred to.

通常,容器能够在构造函数调用之前加载Portlet所需的类。 与可能包含许多类和库的整个应用程序相比,已加载的Portlet被视为次要部分。 因此,规范要求必须使用与加载的Portlet所引用的Portlet应用程序其余部分相同的classloader来完成Portlet类的加载。

The Portlet container may decide to create an instance of your loaded Portlet’s class either when the Portlet container starts the Portlet application (WAR) or when the container determines that Portlet is used to serve certain request.

当Portlet容器启动Portlet应用程序(WAR)或容器确定Portlet用于满足某些请求时,Portlet容器可能会决定创建已加载的Portlet类的实例。

The most important thing that you must take care of is the time needed of Portlet’s resources to be initialized, for which the Portlet would wait until it’s finished to serve the first request. Once the first request has served, every request that’s coming after so would be served normally.

您必须注意的最重要的事情是初始化Portlet资源所需的时间,Portlet将等待该时间完成,直到完成为第一个请求。 一旦第一个请求得到处理,那么随后的每个请求将被正常处理。

While initialization the Portlet is passed an Object instance of PortletConfig interface that’s considered unique to the Portlet definition and provides access to the initialization parameters and the resource bundle configured for the Portlet in the Portlet definition.

在初始化Portlet时,会传递PortletConfig接口的Object实例,该对象实例被视为Portlet定义的唯一实例,并提供对初始化参数和为Portlet定义中的Portlet配置的资源束的访问。

Until the init() method has been invoked successfully, the Portlet isn’t considered as an active Portlet. In case your Portlet class has provided some of static initialization blocks, they must not trigger any methods that make this assumption.

在成功调用init()方法之前,该Portlet不会被视为活动Portlet。 如果您的Portlet类提供了一些静态初始化块,则它们不得触发任何进行此假设的方法。

You can use the Portlet configuration object (PortleConfig) for providing a lot of configurations that’s meant for the Portlet itself like a database connection URL and others.

您可以使用Portlet配置对象( PortleConfig )提供许多针对Portlet本身的配置,例如数据库连接URL等。

Init() method is error-prone by its nature, you may access a database that’s already down or you don’t have a proper permission over it. For such cases, init() has defined as it throws a PortletException. You may also can throw an UnavailableException in between, but regardless of the exception type being thrown, you must ensure that all resources that been acquired are released as the destroy() method won’t be called subsequently. However, failure of initialization does mean that the Portlet container won’t place the Portlet object into active service and it must release the Portlet object.

Init()方法本质上很容易出错,您可能会访问已关闭的数据库,或者您对该数据库没有适当的权限。 对于这种情况, init()已定义为引发PortletException 。 您也可以在两者之间抛出UnavailableException ,但是无论抛出何种异常类型,都必须确保释放所有已获取的资源,因为随后不会调用destroy()方法。 但是,初始化失败确实意味着Portlet容器不会将Portlet对象置于活动服务中,它必须释放Portlet对象。

According to Java Portlet Specification 2.0, the Portlet container may reattempt to instantiate and initialize the Portlets at any time after failure. In case you’ve used UnavilableException and provided a wait time, the Portlet container must wait for the specified time before creating and initializing a new Portlet object. Practically, this feature

根据Java Portlet Specification 2.0,Portlet容器可以在失败后的任何时间重新尝试实例化和初始化Portlet。 如果您已使用UnavilableException并提供了等待时间,则Portlet容器必须等待指定的时间才能创建和初始化新的Portlet对象。 实际上,此功能

In case you’ve got a RuntimeException during initialization, it must be handled as a PortletException.

如果在初始化过程中遇到RuntimeException ,则必须将其作为PortletException进行处理。

请求处理阶段 (Request Handling Stage)

Once the Portlet get initialized, it’s become waiting for users interactions. The interactions with the Portlets can be done through set of requests, these requests are translated into render() and processAction() requests.

一旦Portlet初始化,它就开始等待用户交互。 与Portlet的交互可以通过一组请求完成,这些请求被转换为render()processAction()请求。

Action requests are are asking the Portlets to change the state of its underlying application, while the render requests are displaying the Portlet with its current states. Practically, a subsequent render() request has been initiated once the processAction() got finished.

动作请求正在要求Portlet更改其基础应用程序的状态,而渲染请求正在显示具有当前状态的Portlet。 实际上,一旦processAction()完成,便会启动后续的render()请求。

As we’ve stated previously, you can make a render request and action request by calling createRenderURL() and createActionURL() respectively against passed response object.

如前所述,您可以通过分别对传递的响应对象调用createRenderURL()createActionURL()来发出渲染请求和动作请求。

Generally, RenderRequest that’s passed for render() method is responsible for providing:

通常,传递给render()方法的RenderRequest负责提供:

  • The state of the Portlet window (minimized, maximized, etc.)Portlet窗口的状态(最小化,最大化等)
  • The mode of the Portlet (e.g VIEW, EDIT, etc.)Portlet的模式(例如VIEW,EDIT等)
  • The context of the Portlet.Portlet的上下文。
  • The session associated with the Portlet (including authorization information).与Portlet关联的会话(包括授权信息)。
  • The preferences information associated with the Portlet.与Portlet关联的首选项信息。
  • Any render parameters that have been set on a render URL from a posted form or that have been set during the processAction() method.从发布表单在渲染URL上设置的任何渲染参数,或在processAction()方法期间设置的任何渲染参数。

RenderResponse is also responsible of writing the Portlet’s content fragment into Portal page as it’s also capable to render URLs into that content, which will invoke actions to the Portlet (e.g createActionURL(), createRenderURL(), etc).

RenderResponse还负责将Portlet的内容片段写入门户网站页面,因为它还能够将URL呈现到该内容中,这将调用对Portlet的操作(例如createActionURL() ,createRenderURL()等)。

ActionRequest object represents the opportunity to change the state of the Portlet, it provides everything that’s already offered by PortletRequest along with direct access to the content of the HTTP request made by the user of the Portal. To respond to processAction() the Portlet should update its ActionResponse object which provides methods to:

ActionRequest对象代表更改Portlet状态的机会,它提供PortletRequest已经提供的所有内容,以及对门户网站用户发出的HTTP请求内容的直接访问。 为了响应processAction() ,Portlet应该更新其ActionResponse对象,该对象提供以下方法:

  • Redirect the client to a new Page.将客户端重定向到新的页面。
  • Change the mode of the Portlet.更改Portlet的模式。
  • Add or modify rendering parameters for the user’s session.添加或修改用户会话的渲染参数。

The processAction() proposed above makes a trivial change for the actionCount counter and so it doesn’t have to inform the container of any changes via the response. Following sample shows you how can use the ActionResponse to make a change in the response.

上面建议的processAction()actionCount计数器进行了微不足道的更改,因此不必通过响应将任何更改通知容器。 以下示例显示了如何使用ActionResponse来更改响应。

package com.journaldev.portlet;import java.io.IOException;import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;public class LifecyclePortlet implements Portlet {private static int renderCount = 0;private static int actionCount = 0;private static int initCount = 0;@Overridepublic void init(PortletConfig config) throws PortletException {initCount++;}@Overridepublic void processAction(ActionRequest request, ActionResponse response)throws PortletException, IOException {synchronized(this){actionCount++;}response.sendRedirect(request.getContextPath()+"/index.html");}@Overridepublic void render(RenderRequest request, RenderResponse response)throws PortletException, IOException {synchronized(this){renderCount++;}response.getWriter().print("<form action="+response.createActionURL()+">"+ "<p> The number of initiated Portlets by the container is :: "+initCount+"</p>"+ "<p> The number of processed actions by the container is :: "+actionCount+"</p>"+ "<p> The number of achieved render by the container is :: "+renderCount+"</p>"+"<input value='Submit' type='submit'/><br/>"+ "<a href='"+response.createRenderURL()+"'>Render Again</a>"+ "</form>");}@Overridepublic void destroy() {initCount--;System.out.println("The number of Portlets get deployed :: "+initCount);}}

index.html

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>ActionResponse Sample</title>
</head><body><p>ActionResponse redirects the client into this page</p></body>
</html>

Here’s some of important points need to notice:

这里有一些重要的注意事项:

  • Determine of context path of Portlet application has been done through using of ActionRequest.已经通过使用ActionRequest确定了Portlet应用程序的上下文路径。
  • ActionResponse does redirect the action request to be served by using different content (i.e index.html).ActionResponse确实通过使用其他内容(即index.html)来重定向要处理的操作请求。

Portlet销毁阶段 (Portlet Destroying Stage)

As we’ve stated earlier, the destroy() method won’t be invoked as a subsequent phase when the initialization phase is failed. To allow Portlet container from destroying a certain Portlet, the Portlet must be instantiated and initialized successfully and all processing threads on the Portlet’s instance have completed.

如前所述,初始化阶段失败时,不会将destroy()方法作为后续阶段调用。 为了允许Portlet容器销毁某个Portlet,必须成功实例化和初始化Portlet,并且必须完成Portlet实例上的所有处理线程。

If you’ve integrated with third parties, the destroy() method is the best place to notify those third parties about the Portlet is becoming unavailable. According for Java Portlet Specification 2.0, after destroy() method completes, the Portlet container must release the Portlet object so that it’s eligible for garbage collection. Portlet implementations shouldn’t use finalizers.

如果您已与第三方集成,则destroy()方法是通知这些第三方有关Portlet变得不可用的最佳位置。 根据Java Portlet Specification 2.0,在destroy()方法完成之后,Portlet容器必须释放Portlet对象,以便可以进行垃圾回收。 Portlet实现不应使用终结器

线程问题 (Threading Issues)

According to Java Portlet Specification 2.0, The Portlet container is able to handle the requests concurrently. Portlet developers must design their Portlets to handle concurrent execution from multiple threads from within the processAction() and render() methods or any of the optional lifecycle methods, like prcoessEvent() or serveResource(), at any particular time.

根据Java Portlet Specification 2.0,Portlet容器能够同时处理请求。 Portlet开发人员必须设计其Portlet,以在任何特定时间处理processAction()render()方法或任何可选的生命周期方法(例如prcoessEvent()serveResource()内多个线程的并发执行。

Actually, implementations of the request and response objects aren’t guaranteed to be thread safe. This means that they must only be used within the scope of thread invoking the processAction(), render(), processEvent() and serveResource() methods.

实际上,不能保证请求和响应对象的实现是线程安全的。 这意味着它们只能在调用processAction()render()processEvent()serveResource()方法的线程范围内使用。

To remain Portable, Portlet applications shouldn’t give references of the request and response objects to objects executing in other threads as the resulting may be non-deterministic.

为了保持可移植性,Portlet应用程序不应将请求和响应对象的引用提供给在其他线程中执行的对象,因为结果可能是不确定的。

In other words, any combination and number of simultaneous calls to render() and/or processAction() would be safe unless the Portlet has used an instance variables and/or external resources.

换句话说,除非Portlet使用实例变量和/或外部资源,否则同时调用render()和/或processAction()任何组合和数量都是安全的。

As we’ve stated earlier at the provided sample, all counters had defined as an instance variables and so, they’re not safe when it comes to be processed by concurrent threads. For handling increments for all of them concurrently, we’ve stated them within a synchronized block.

正如我们之前在提供的示例中所述,所有计数器都已定义为实例变量,因此,当它们被并发线程处理时,它们是不安全的。 为了同时处理所有这些增量,我们在一个同步块中声明了它们。

Portlet生命周期摘要 (Portlet Lifecycle Summary)

Similar for Servlet, user requests for Portlet are handled through well-defined lifecycle that’s maintained by the Portlet container. This tutorial has focused on the lifecycle and its details as well as for threading issue. Contribute us by commenting below and find downloaded source code.

与Servlet类似,用户对Portlet的请求是通过Portlet容器维护的定义明确的生命周期来处理的。 本教程重点讨论生命周期及其详细信息以及线程问题。 通过在下面评论来贡献我们,并找到下载的源代码。

Download Portlet Lifecycle Example Project下载Portlet生命周期示例项目

翻译自: https://www.journaldev.com/4732/portlet-lifecycle

portlet

portlet_Portlet生命周期相关推荐

  1. LTV 即用户生命周期价值

    20220321 https://mp.weixin.qq.com/s/kPoojfRCbvCCV4zpnCimmQ 指标计算详细介绍 数据分析|如何做好用户生命周期价值分析 LTV https:// ...

  2. Harmony生命周期

    Harmony生命周期 系统管理或用户操作等行为,均会引起Page实例在其生命周期的不同状态之间进行转换.Ability类提供的回调机制能够让Page及时感知外界变化,从而正确地应对状态变化(比如释放 ...

  3. Activity在有Dialog时按Home键的生命周期

    当一个Activity弹出Dialog对话框时,程序的生命周期依然是onCreate() - onStart() - onResume(),在弹出Dialog的时候并没有onPause()和onSto ...

  4. 横竖屏切换时Activity的生命周期

    1.不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏执行一次,切竖屏执行两次. 2.设置Activity的android:configChang ...

  5. Android中Service生命周期、启动、绑定、混合使用

    一.Activity和Service如何绑定: 1.Service和Activity之间的连接可以用ServiceConnection来实现.实现一个ServiceConnection对象实例,重写o ...

  6. Cocos生命周期回调

    Cocos Creator 为组件脚本提供了生命周期的回调函数.用户只要定义特定的回调函数,Creator 就会在特定的时期自动执行相关脚本,用户不需要手工调用它们. 目前提供给用户的生命周期回调函数 ...

  7. Fragment 使用 replace 的方式实现切换 以及切换的时候Fragment 生命周期

    这个主要代码在activity里面 如下 public class ReplaceActivity extends AppCompatActivity implements View.OnClickL ...

  8. Fragment 使用 show 和 hide 的方式实现切换 以及切换的时候Fragment 生命周期

    实现的效果如下图 主要的代码在activity 这里贴出来了 public class ShowActvity extends AppCompatActivity implements View.On ...

  9. ViewPager与Fragment结合使用,以及切换的时候Fragment 的生命周期

    下面要做的效果图下图 首先我们创建一个适配器如下 public class FraPagerAdapter extends FragmentPagerAdapter {private List< ...

最新文章

  1. 青龙羊毛——东方头条(搬砖,非原创)
  2. 如何快速接手一个系统?
  3. 在Junit上使用Kafka
  4. 山东科技大学计算机等级,关于2019年03月全国计算机等级考试报名工作的通知
  5. JRebel Idea热更新插件
  6. c语言程序女设计教学效果分析,C语言程序设计的教学论文
  7. 计算机网络之网络安全基础
  8. Visual Assist X 10.8.2001 破解版 支持VC2013及以下版本
  9. OA实施周期:易用性才是关键因素
  10. 人在广州,力撑陈 Sir
  11. pycharm创建django项目时出错
  12. 苏州科技大学的计算机专业怎么样,苏州科技大学怎么样?有什么王牌专业?排名如何?...
  13. 计算机黑屏但是有鼠标,电脑黑屏但是鼠标能动解决方法
  14. ps 帧动画 也说 gif 动图
  15. miredo - Teredo IPv6 tunneling for Unix
  16. 小程序开发API之地图wx.createMapContext及MapContext 实例
  17. 如何使用Git进行团队协作开发
  18. AngularJS vs. jQuery,看看谁更胜一筹
  19. DCB工作机制解析三(CN)
  20. lindo中的0-1约束

热门文章

  1. fstab损坏无法开机的修复
  2. [转载] 用python写的一个简单的记事本
  3. [转载] Python中的数学函数,三角函数,随机数函数
  4. 使用jsPlumb插件实现动态连线功能
  5. 站内搜索(ELK)之数据表字典类型字段的索引思路
  6. 2016/09/19
  7. 详细介绍android rom移植知识普及
  8. windows下如何使用QT编写dll程序 .
  9. 为什么需要使用Git客户端?
  10. freemarker处理嵌套属性是否为空的判断