Android Networking Bare Skin——理解JPost
如果你想在 Android 上创建自下而上的网络,通常是相当复杂的。因此,我们依赖第三方库。但你永远不会知道它下面是什么。在这个例子中,我使用了网络Java.net 包来创建一个由 JPost 驱动的网络框架,一个类通信框架。
日本邮政
这是一个Java / Android 库,它允许类以模块化、异步和规范的方式进行通信。以下是该库的主要特点:
- 与之前的 pub-sub 库相比,它对订阅者的引用很弱。因此,它不会导致内存泄漏。
- 可以将单个消息发送给订阅者的子集。这可以防止在不利位置接收事件的问题。结果,异常应用行为的可能性降低了。
- 专用频道可用于管理订阅者添加。它减少了无意中订阅订阅者和接收不需要的通信的可能性。
- 这是一个小图书馆(55kb)。因此,应用程序的总大小不受影响。
- 它支持同步和异步消息传输和处理。
- 它提供了一种异步运行程序的技术。
我们究竟要构建什么?
我们将创建一个 Android 应用程序,该应用程序将执行网络调用以检索用户的存储库并将其显示在 ListView 中。结果显示在下面的屏幕截图中。
第1步:
首先创建一个 Android Studio 项目并选择“Empty Activity”模板。选择空活动后,我们现在准备完成工作并使项目发生。将以下库导入应用程序模块的 build.gradle:
dependencies {
implementation 'com.geeks-for-geeks-jpost:0.0.4'
implementation 'com.google.code.gson:gson:2.7'
}
GeekTip: Json is a well-known JSON parsing library. It aids in the conversion of an object to a json object and vice versa. As previously stated, JPost is a class communication library.
第 2 步:设计 MainActivity 布局
我们现在将完成设计 UI 的繁重任务,这通常是基本的,因为这只是一个教程。
XML
XML
Java
public class GeeksforGeeks extends android.app.Application {
@Override
public void onCreate() {
// Simply call the super method
super.onCreate();
// Add the API handler here
sampleAPIHandler.init();
}
}
Java
public class GfgRepoGit {
@SerializedName("sno")
private Integer sno;
@SerializedName("specimen_name")
private String specimen_name;
@SerializedName("url ")
private String url;
@SerializedName("weight")
private Integer weight;
public Integer fetchID() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String fetchname() {
return theName;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer size) {
this.size = weight;
}
}
Java
public class GfGRepoMsg{
private static List< GfGRepoMsg> gfgRepoList;
public GfGRepoMsg (List gitRepoList) {
this.gitRepoList = gitRepoList;
}
public List getGfgRepo() {
return gfgRepo;
}
public void setGitRepoList(List gitRepoList) {
this.gitRepoList = gitRepoList;
}
}
Java
public class gfgRepoList extends BaseAdapter {
private List gfgRepoList;
private Context gfgcontext;
public RepoListAdapter(Context gfgcontext, List gfgRepoSize) {
this.gfgcontext = gfgcontext;
this.gfgRepoSize = gfgRepoSize;
}
@Override
public int getCount() {
return gfgRepoSize.size();
}
@Override
public Object getItem(int someGfgPosition) {
return gfgRepoSize.get(someGfgPosition);
}
@Override
public long getItemId(int someGfgPosition) {
return someGfgPosition;
}
@Override
public View getView(int someGfgPosition, View gfgView, ViewGroup parent) {
final ViewHolder holder;
if(gfgView == null){
gfgView = LayoutInflater.from(gfgcontext).inflate(R.layout.gfg_list_item,parent,false);
holder = new ViewHolder();
gfgView.setTag(holder);
}else{
holder=(ViewHolder)gfgView.getTag();
}
holder.geeksRepoIdTxt = (TextView)gfgView.findViewById(R.id.sampleRepo);
holder.geeksRepoNameTxt = (TextView)gfgView.findViewById(R.id.sampleName);
holder.geeksRepoUrlTxt = (TextView)gfgView.findViewById(R.id.sampleUrl);
holder.geeksRepoSizeTxt = (TextView)gfgView.findViewById(R.id.sampleRepo);
gfgRepoList geeksRepo = gfgRepoSize.get(someGfgPosition);
holder.geeksRepoIdTxt.setText(String.valueOf(geeksRepo.getId()));
holder.geeksRepoNameTxt.setText(geeksRepo.getName());
holder.geeksRepoUrlTxt.setText(geeksRepo.getUrl());
holder.geeksRepoSizeTxt.setText(String.valueOf(geeksRepo.getSize()));
return gfgView;
}
private class ViewHolder{
TextView geeksRepoIdTxt;
TextView geeksRepoNameTxt;
TextView geeksRepoUrlTxt;
TextView geeksRepoSizeTxt;
}
public void setgfgRepoListList(List gfgRepoSize) {
this.gfgRepoSize = gfgRepoSize;
notifyDataSetChanged();
}
}
Java
public class sampleAPIHandler{
public static String GIT_REPO_URL = "https://api.github.com/users/the-rebooted-coder/repos";
private static final int RANDOM_CHANNEL_ID = 1000;
private static sampleAPIHandler sampleapihandler;
public static void init(){
sampleapihandler = new sampleAPIHandler();
}
public sampleAPIHandler() {
try {
JPost.getBroadcastCenter().createPrivateChannel(this, RANDOM_CHANNEL_ID );
}catch (Exception e){
e.printStackTrace();
}
}
public static void DOASERVICECALL(String url){
try {
JPost.getBroadcastCenter().broadcastAsync(sampleapihandler, RANDOM_CHANNEL_ID , url);
}catch (JPostNotRunningException e){
e.printStackTrace();
}
}
@OnMessage(channelId = RANDOM_CHANNEL_ID )
public void processGitRepoGet(String url) {
try {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
Log.d("Debug", "GEEKS FOR GEEKS : " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
Log.d("Debug", "Response : " + response);
GEEKSSONBuilder builder = new GEEKSSONBuilder();
GEEKSSON GEEKSSON = builder.create();
GitRepo[] gitRepoArray = GEEKSSON.fromJson(response.toString(), GitRepo[].class);
JPost.getBroadcastCenter().broadcastAsync(new GitRepoMsg(Arrays.asList(gitRepoArray)));
}
}catch (MalformedURLException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (JPostNotRunningException e){
e.printStackTrace();
}
}
}
Java
public class MainActivity extends AppCompatActivity {
private ListView GFGREPOLIST;
private RepoListAdapter GFGLIST;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GFGREPOLIST = (ListView) findViewById(R.id.GFGREPOLIST);
GFGLIST = new RepoListAdapter(getApplicationContext(), new ArrayList());
GFGREPOLIST.setAdapter(GFGLIST);
try {
JPost.getBroadcastCenter().addSubscriber(this);
}catch (Exception e){
e.printStackTrace();
}
SAMPLEAPIHANDLER.DOSERVICECALL(SAMPLEAPIHANDLER.GIT_REPO_URL);
}
@OnUiThread
@OnMessage
private void onGitRepoList(GitRepoMsg msg){
if(msg.getGitRepoList() != null) {
GFGLIST.setGitRepoList(msg.getGitRepoList());
}
}
}
GeekTip: It features a ListView to display the elements in a vertical list.
第 3 步:创建列表项视图布局
就像上一步一样,您现在需要创建一个列表项视图,如步骤 #2 中所做的那样,只需执行以下操作即可创建它:
XML
GeekTip: It has four-row views that display four properties from the API response.
第 4 步:创建一个扩展 android.app 的类,名为 GeeksforGeeks
利用率:我们希望初始化我们正在开发的网络框架。因此,我们必须指定程序何时启动。
Java
public class GeeksforGeeks extends android.app.Application {
@Override
public void onCreate() {
// Simply call the super method
super.onCreate();
// Add the API handler here
sampleAPIHandler.init();
}
}
第 5 步:创建一个将根据 JSON 响应构建的数据模型类
最后,我们需要做的最后一件事就是创建一个数据模型类,它使我们能够获取和设置调用 API 的数据。
Java
public class GfgRepoGit {
@SerializedName("sno")
private Integer sno;
@SerializedName("specimen_name")
private String specimen_name;
@SerializedName("url ")
private String url;
@SerializedName("weight")
private Integer weight;
public Integer fetchID() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String fetchname() {
return theName;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer size) {
this.size = weight;
}
}
GeekTip:“@SerializedName” is a JSON library annotation that maps the variable to the JSON key.
第 6 步:创建 GitRepoMsg 类
现在我们将创建一个 GfGRepoMsg 类,该类将用作在我们稍后构建的通道上传输解析的 JSON 响应的消息。
Java
public class GfGRepoMsg{
private static List< GfGRepoMsg> gfgRepoList;
public GfGRepoMsg (List gitRepoList) {
this.gitRepoList = gitRepoList;
}
public List getGfgRepo() {
return gfgRepo;
}
public void setGitRepoList(List gitRepoList) {
this.gitRepoList = gitRepoList;
}
}
第 7 步:制作一个名为 gfgRepoList 的列表视图适配器来填充 ListView
下一步显然是创建一个 gfgRepoList 适配器,然后填充将设置数据的列表视图;
Java
public class gfgRepoList extends BaseAdapter {
private List gfgRepoList;
private Context gfgcontext;
public RepoListAdapter(Context gfgcontext, List gfgRepoSize) {
this.gfgcontext = gfgcontext;
this.gfgRepoSize = gfgRepoSize;
}
@Override
public int getCount() {
return gfgRepoSize.size();
}
@Override
public Object getItem(int someGfgPosition) {
return gfgRepoSize.get(someGfgPosition);
}
@Override
public long getItemId(int someGfgPosition) {
return someGfgPosition;
}
@Override
public View getView(int someGfgPosition, View gfgView, ViewGroup parent) {
final ViewHolder holder;
if(gfgView == null){
gfgView = LayoutInflater.from(gfgcontext).inflate(R.layout.gfg_list_item,parent,false);
holder = new ViewHolder();
gfgView.setTag(holder);
}else{
holder=(ViewHolder)gfgView.getTag();
}
holder.geeksRepoIdTxt = (TextView)gfgView.findViewById(R.id.sampleRepo);
holder.geeksRepoNameTxt = (TextView)gfgView.findViewById(R.id.sampleName);
holder.geeksRepoUrlTxt = (TextView)gfgView.findViewById(R.id.sampleUrl);
holder.geeksRepoSizeTxt = (TextView)gfgView.findViewById(R.id.sampleRepo);
gfgRepoList geeksRepo = gfgRepoSize.get(someGfgPosition);
holder.geeksRepoIdTxt.setText(String.valueOf(geeksRepo.getId()));
holder.geeksRepoNameTxt.setText(geeksRepo.getName());
holder.geeksRepoUrlTxt.setText(geeksRepo.getUrl());
holder.geeksRepoSizeTxt.setText(String.valueOf(geeksRepo.getSize()));
return gfgView;
}
private class ViewHolder{
TextView geeksRepoIdTxt;
TextView geeksRepoNameTxt;
TextView geeksRepoUrlTxt;
TextView geeksRepoSizeTxt;
}
public void setgfgRepoListList(List gfgRepoSize) {
this.gfgRepoSize = gfgRepoSize;
notifyDataSetChanged();
}
}
GeekTip: The adapter is given a list of GitRepo objects to populate the list item views with. The setGitRepoList function re-initializes the list and calls the repopulateListItemViews method to populate the list item views with fresh data.
第 8 步:要管理 API 调用,请创建 sampleAPIHandler 类
我们先来看看这个类,然后我们尝试去理解它:
Java
public class sampleAPIHandler{
public static String GIT_REPO_URL = "https://api.github.com/users/the-rebooted-coder/repos";
private static final int RANDOM_CHANNEL_ID = 1000;
private static sampleAPIHandler sampleapihandler;
public static void init(){
sampleapihandler = new sampleAPIHandler();
}
public sampleAPIHandler() {
try {
JPost.getBroadcastCenter().createPrivateChannel(this, RANDOM_CHANNEL_ID );
}catch (Exception e){
e.printStackTrace();
}
}
public static void DOASERVICECALL(String url){
try {
JPost.getBroadcastCenter().broadcastAsync(sampleapihandler, RANDOM_CHANNEL_ID , url);
}catch (JPostNotRunningException e){
e.printStackTrace();
}
}
@OnMessage(channelId = RANDOM_CHANNEL_ID )
public void processGitRepoGet(String url) {
try {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
Log.d("Debug", "GEEKS FOR GEEKS : " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
Log.d("Debug", "Response : " + response);
GEEKSSONBuilder builder = new GEEKSSONBuilder();
GEEKSSON GEEKSSON = builder.create();
GitRepo[] gitRepoArray = GEEKSSON.fromJson(response.toString(), GitRepo[].class);
JPost.getBroadcastCenter().broadcastAsync(new GitRepoMsg(Arrays.asList(gitRepoArray)));
}
}catch (MalformedURLException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (JPostNotRunningException e){
e.printStackTrace();
}
}
}
GeeksTip: GIT GFG is defined to make referencing the API endpoint from any class easier. SAMPLE_CHANNEL_ID is the int id that we wish to associate with a private channel that we’ve created using JPost. JPost offers three types of channels. The default, public, and private channels are used to connect with users in a regulated manner. Only the Creator may add subscribers to this channel, and only subscribers can publish messages on it. For additional information, please visit JPost.
The ApiHandler class is instantiated using the init function.
第 9 步:创建 MainActivity
我们需要执行的最后一步是创建我们将用于数据获取的主要活动:
Java
public class MainActivity extends AppCompatActivity {
private ListView GFGREPOLIST;
private RepoListAdapter GFGLIST;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GFGREPOLIST = (ListView) findViewById(R.id.GFGREPOLIST);
GFGLIST = new RepoListAdapter(getApplicationContext(), new ArrayList());
GFGREPOLIST.setAdapter(GFGLIST);
try {
JPost.getBroadcastCenter().addSubscriber(this);
}catch (Exception e){
e.printStackTrace();
}
SAMPLEAPIHANDLER.DOSERVICECALL(SAMPLEAPIHANDLER.GIT_REPO_URL);
}
@OnUiThread
@OnMessage
private void onGitRepoList(GitRepoMsg msg){
if(msg.getGitRepoList() != null) {
GFGLIST.setGitRepoList(msg.getGitRepoList());
}
}
}
GeekTip:
- Using the addSubscriber(object) function, MainActivity subscribes to JPost’s Default Channel.
- “@OnUiThread” : It’s an annotation provided to Android. To know more about annotation in android, click here
- It receives the response message over the global default channel and refreshes the listview.
结论
就是这样!您可能会感谢 JPost 创建了如此简单而强大的网络基础设施。这是指导方针的一个例子。通往完全开发系统的道路留作练习。