在使用Espresso時,輸入指令 $gradle connectedInstrumentTest 時遇到以下問題
Failed to apply plugin [id 'com.android.application']
> Gradle version 1.10 is required. Current version is 2.2. If using the gradle wrapper, try editing the distributionUrl in /Users/xxxx/AndroidStudioProjects/xxxxx/gradle/wrapper/gradle-wrapper.properties to gradle-1.10-all.zip
二、解決辦法
訊息:
"Gradle version 1.10 is required. Current version is 2.0"
以下內容來源︰stackoverflow Lets start with a bit of background: What happens when you start an application?
我們來談一些關於android背後的機制︰當你啟動了一個應用程式(application)後,背後究竟發生了些什麼事?
The OS starts a process and assigns it a unique process id and allocates a process table.A process start an instance of DVM(Dalvik VM); Each application runs inside a DVM.
在啟動了一個應用程式以後,作業系統開啟了一個進程(process),並同時給這個進程一個專屬進程id,並分配給進程一個進程資料表(process table,用來儲存該進程的所有相關資訊)。然後,這個進程會啟動一個DVM(Dalvik VM,Dalvik虛擬機)實體,每一個應用程式(application)都分別運作在各自的DVM裡。
A DVM manages class loading unloading, instance lifecycle, GC etc.
DVM管理著每個class是否要被載入(loading unloading)、生命週期、實體、資源回收(Garbage Collection)等等。
Lifetime of a static variable: A static variable comes into existence when a class is loaded by the JVM and dies when the class is unloaded.
static變數的生命週期︰當一個class被JVM載入後,static變數值就會被產生,當class被卸載後,static變數值就會被消毀。
So if you create an android application and initialize a static
variable, it will remain in the JVM until one of the following happens:
1. the class is unloaded
2. the JVM shuts down
3. the process dies Note that the value of the static variable will persist when you
switch to a different activity of another application and none of the
above three happens. Should any of the above three happen the static
will lose its value.
所以,當你建立了一個android應用程式並且初始化了static變數後,這個static值就會被保留直到下列事件發生為止︰
1.class被卸載
2.JVM被關閉
3.進程(process)被消滅了 備註︰當你切換到不同的應用程式的Activity時,原Activity的static變數都會一直被保留,除非上述的事件被觸發。一旦被觸發後,static變數就會遺失原來的值。
You can test this with a few lines of code: 1.print the uninitialized static in onCreate of your activity -> should print null 2.initialize the static. print it -> value would be non null 3.Hit the back button and go to home screen. Note: Home screen is another activity. 4.Launch your activity again -> the static variable will be non-null 5.Kill your application process from DDMS(stop button in the devices window). 6.Restart your activity -> the static will have null value.
你可以用下列的方式試試上述的理論︰
1.在Activity onCreate()函式裡印岀未初始化的static變數值-->應該印岀null。
2.初始化static變數值-->印岀來的值應該就不是null值了。
3.點擊手機返回鍵並回到手機Home首頁(備註︰Home首頁就是另一個Activity)。
4.重啟你的Activity-->static變數值理論上不會是null。
5.從DDMS砍掉你的應用程式進程(在Eclipse ADT裡有一個Devices視窗,裡面有stop按鈕,見下圖)。
6.重啟你的Activity-->static變數值將會變成null。
package recyclerview.android.hmkcode.com.recyclerview;
/**
* Created by lp43 on 2014/8/4.
*/
public class ItemData {
private String title;
private String imageUrl;
public ItemData(String title,String imageUrl){
this.title = title;
this.imageUrl = imageUrl;
}
public String getTitle() {
return title;
}
public String getImageUrl() {
return imageUrl;
}
public void setTitle(String title) {
this.title = title;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
實作RecyclerView的Adapter-->MyAdapter.java
package recyclerview.android.hmkcode.com.recyclerview;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
/**
* Created by lp43 on 2014/8/4.
*/
public class MyAdapter extends RecyclerView.Adapter{
private ItemData[] itemsData;
public MyAdapter(ItemData[] itemsData) {
this.itemsData = itemsData;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
// create a new view
View itemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
viewHolder.txtViewTitle.setText(itemsData[position].getTitle());
// viewHolder.imgViewIcon.setImageResource(itemsData[position].getImageUrl());
Picasso.with(viewHolder.imgViewIcon.getContext()).cancelRequest(viewHolder.imgViewIcon);
Picasso.with(viewHolder.imgViewIcon.getContext()).load(itemsData[position].getImageUrl()).into(viewHolder.imgViewIcon);
}
// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
return itemsData.length;
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txtViewTitle;
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
itemLayoutView.setOnClickListener(this);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
}
@Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "position = " + getPosition(), Toast.LENGTH_SHORT).show();
}
}
}
在主頁面MyActivity.java實例化RecyclerView
package recyclerview.android.hmkcode.com.recyclerview;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
public class MyActivity extends ActionBarActivity {
private String[] sources = {
"http://lorempixel.com/600/250/",
"http://lorempixel.com/600/250/sports",
"http://lorempixel.com/600/200/sports/Dummy-Text",
"http://lorempixel.com/600/200/nature",
"http://lorempixel.com/600/200/food",
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// this is data fro recycler view
ItemData[] itemsData = {
new ItemData("Delete",sources[0]),
new ItemData("Cloud",sources[1]),
new ItemData("Favorite",sources[2]),
new ItemData("Like",sources[3]),
new ItemData("Rating",sources[4]),
new ItemData("Delete",sources[0]),
new ItemData("Cloud",sources[1]),
new ItemData("Favorite",sources[2]),
new ItemData("Like",sources[3]),
new ItemData("Rating",sources[4])
};
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 3. create an adapter
MyAdapter mAdapter = new MyAdapter(itemsData);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
// 5. set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}