我目前正在使用Reflection使用class.memberProperties
函数在运行时检查元素。 properties
的类型为collection<KProperty1<I, *>>
,因此我遍历每个KProperty
对象,通过检查名称是否等于“ nameIWant”来找到所需的对象,尽管我会而是能够通过在KProperty
上使用.get()
方法从property
获取属性的实例,这样我就可以进行如下检查:
if (property.get(receiver) is ClassIWant) {
//Do something
}
我的代码如下:
val properties = request.payload::class.memberProperties
properties.forEach { property ->
run {
if (property.name.equals("nameIWant")) {
}
}
}
到目前为止,我一直在尝试对.get()
类型使用KProperty1
方法,但是它接受类型为receiver
的参数Nothing
。我无法计算出要调用.get()
方法并获取属性的特定实例所需要传递的内容。我还检查了以下文档:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property1/index.html,但实际上并没有帮助。
答案 0 :(得分:0)
您可以为package altis.trackingapp.track;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
String latitude="";
String longitude="";
String imei;
private static String url;
String status;
Double myLat=0.0;
Double myLng=0.0;
private String TAG = MapsActivity.class.getSimpleName();
private ProgressDialog pDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
latitude=getIntent().getStringExtra("latitude");
longitude=getIntent().getStringExtra("longitude");
imei=getIntent().getStringExtra("imei");
url = "http://139.162.37.96/track/api2/geteventstatus.php?imei="+imei;
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
new GetEventStatus().execute();
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
myLat = Double.parseDouble(latitude);
myLng = Double.parseDouble(longitude);
Toast.makeText(MapsActivity.this, "Lat:"+myLat+"\tLng:"+myLng, Toast.LENGTH_LONG).show();
if (myLat==0 && myLng==0) {
Toast.makeText(MapsActivity.this,"Invalid Location",Toast.LENGTH_SHORT).show();
Intent dev = new Intent(MapsActivity.this,DevicesNavActivity.class);
startActivity(dev);
}
else if (myLat==null && myLng==null) {
Toast.makeText(MapsActivity.this,"No Data Found",Toast.LENGTH_SHORT).show();
Intent dev = new Intent(MapsActivity.this,DevicesNavActivity.class);
startActivity(dev);
}
else {
LatLng location = new LatLng(myLat, myLng);
//Adding Marker to Location
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(location)
.title("Marker")
.snippet("My Marker")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
//Displaying the Info Window
InfoWindowData info = new InfoWindowData();
info.setName("Co-Ordinates of "+imei);
info.setLatitude(latitude);
info.setLongitude(longitude);
CustomInfoWindowActivity customInfoWindow = new CustomInfoWindowActivity(this);
mMap.setInfoWindowAdapter(customInfoWindow);
Marker m = mMap.addMarker(markerOptions);
m.setTag(info);
m.showInfoWindow();
// Add a marker in Location and move the camera
// mMap.addMarker(new MarkerOptions().position(location).title("Marker"));
//mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 17f));
mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
Intent event = new Intent(MapsActivity.this, EventGenerateActivity.class);
event.putExtra("latitude",latitude);
event.putExtra("longitude",longitude);
event.putExtra("imei",imei);
event.putExtra("status",status);
startActivity(event);
}
});
}
}
/**
* Async task class to get json by making HTTP call
*/
private class GetEventStatus extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr.trim().equals("1"))
status = "1";
else
status = "0";
Log.e(TAG, "Status: " +status);
return null;
}
}
public void onBackPressed()
{
Intent dev = new Intent(MapsActivity.this,DevicesNavActivity.class);
startActivity(dev);
return;
}
}
创建一个KType
,然后检查属性的ClassIWant
。会是这样的:
returnType
您可以将属性变量转换为正确的类型并使用val properties = request.payload::class.memberProperties
val desiredType = ClassIWant::class.createType()
properties.forEach { property ->
if (property.name == "nameIWant" && property.returnType == desiredType) {
//todo
}
}
get
答案 1 :(得分:0)
如果要获取属性的值,请将类转换为不变类型。
instance::class.memberProperties.first() // returns KProperty1<out Instance, *>
(instance::class as KClass<Instance>).memberProperties.first() // returns KProperty1<Instance, *>
如果您的KClass<Instance>
是KClass<*>
,请使用Any
作为Instance
。
为什么KProperty.call
接受Nothing
作为接收者?
因为instance::class
返回KClass<out Instance>
,它将协变类型参数传播到属性,属性变成KProperty<out Instance, *>
,这将可能的方法接收者缩小为Instance的任何子类型,但是因为不知道哪个,我们不能安全地提供Instance的任何实例,如方差规则所示,此处将通用类型参数限制为Nothing
,这意味着根本无法调用该方法。>
为什么::class
设计为协变的?
为了保证安全。这似乎是不合逻辑的,因此一直是大辩论的问题。
如果您想知道该属性可以返回的值的类型,请使用
property.returnType
它返回一个KType,它是Kotlin的Java Type的版本,它是Class(它是Type的一种实现)的更通用的概念。
如果需要将KType“转换”为KClass,则需要执行与将Type转换为Class相同的操作,即获取该类型的原始类型。原始类型是去除所有常规信息的类型,是的,是已擦除类型。完成此操作的方法(似乎)更加复杂(涉及处理每个可能的KType / Type实现),我建议单独检查此问题的答案。
您将能够使用以下方法重用Java实现(您一定会自己找到):
kType.javaType.covertJavaTypeToJavaClass().kotlin // returns KClass<*>
您的问题中的更正。如果您希望获得正确的答案,建议使用适当的术语:
*您问题中的I
是方法接收者的类型,而不是属性的值
* collection
不是类型,Collection is
* property is ClassIWant
不明确,因为property.type
是属性中值的类型,而property::class
只是属性实现,is
也是instanceof
的检查,但是相应地,您需要使用KClass.isSubclassOf
或Java中称为type.isAssignableFrom
的内容(观察通话顺序),然后将您的条件设为ClassIWant.isSuperclassOf(property.type.getRawType())
* instance of the property
属性具有值,而不是实例。只有类具有实例。实例是值,值是(某类的)实例,但是您仍然必须说instance representing the value of the property