我正在使用Reverfit2,我试图从我用Python制作的Web服务中请求一些数据。
实际上,它抛出了一个“java.lang.IllegalStateException”,但是当我调用GET方法时,API返回代码200,而且我还可以看到用于调试响应JSON的打印版本。问题是Call方法,因为它总是在failure时执行。
求求你,救命!
这是我的(简单的)Python Web服务,API-Prueba:
from flask import Flask, jsonify import json import mysql.connector import collections app = Flask(__name__) cnx = mysql.connector.connect(user="root", password="", host="localhost", database="gym") @app.route('/gym/api/v1.0/clases', methods=['GET']) def getClases(): sql = "SELECT id, nombre, descripcion FROM clases" cursor = cnx.cursor() cursor.execute(sql) entradas = cursor.fetchall() # Convertir la query en un array de entradas objects_list = [] for row in entradas: objects_list.append(row) j = json.dumps(objects_list) return j @app.route('/') def index(): return 'Hello, World!' if __name__ == '__main__': app.run(debug=True)
这是我的忠告:
public class ApiClient { private static ApiService REST_CLIENT; private static final String API_URL = "http://10.0.2.2:5000/gym/api/v1.0/"; //Change according to your API path. static { setupRestClient(); } private ApiClient() { } public static ApiService get() { return REST_CLIENT; } private static void setupRestClient() { OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); //Uncomment these lines below to start logging each request. HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); httpClient.addInterceptor(logging); Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .client(httpClient.build()) .build(); REST_CLIENT = retrofit.create(ApiService.class); } }
我的API interace,APIService:
public interface ApiService { @GET("clases") Call> getClases(); }
这是查询API并获取数据的片段,claseFragment:
public class ClaseFragment extends Fragment implements View.OnClickListener { private List clases; private ListView listView; private Button btnRefresh; public ClaseFragment() { // Required empty public constructor } public static ClaseFragment newInstance() { ClaseFragment fragment = new ClaseFragment(); Bundle args = new Bundle(); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View root = inflater.inflate(R.layout.fragment_clase, container, false); listView = (ListView) root.findViewById(R.id.claseList); btnRefresh = (Button) root.findViewById(R.id.btnRefresh); btnRefresh.setOnClickListener(this); getListaClases(); return root; } @Override public void onClick(View v) { //do what you want to do when button is clicked switch (v.getId()) { case R.id.btnRefresh: Log.d(getTag(), "hello"); getListaClases(); break; default: break; } } private void getListaClases() { final ProgressDialog loading = ProgressDialog.show(getActivity(), getContext().getString(R.string.loading_title), getContext().getString(R.string.loading_please_wait), false, false); Call> call = ApiClient.get().getClases(); call.enqueue(new Callback>() { @Override public void onFailure(Call> call, Throwable t) { Log.d("ApiService", "Error Occured: " + t.getMessage()); loading.dismiss(); } @Override public void onResponse(Call> call, Response> response) { Log.d("ApiService", "Successfully response fetched"); loading.dismiss(); if (response.code() == 200 && response.isSuccessful()) { clases = response.body(); showList(); } else { Log.d("APIPlug", "No item found"); } } }); } //Our method to show list private void showList() { Log.d("ApiService", "Show List"); ClaseAdapter adapter = new ClaseAdapter(getActivity(), clases); listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Clase clickedObj = (Clase) parent.getItemAtPosition(position); //If you have detail activity about your object define in here /* Intent detail = new Intent(getContext(), ActorDetail.class); detail.putExtra("actorObject", clickedObj); startActivity(detail); */ } }); } }
这是来自我的web服务的实际响应,我希望将其显示到ListView中:
[
[1, "halterofilia", "Profesor: XXXX YYYY. Clase de Halterofilia."],
[2, "crossfit", "Profesor:ZZZZ TTTT. Clase de CrossFit"],
[3, "halterofilia", "Profesor:XXXX YYYY. Clase de halterofilia"]
]
编辑:
从Android Studio追溯:
D/OkHttp: --> GET http://10.0.2.2:5000/gym/api/v1.0/clases http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- 200 OK http://10.0.2.2:5000/gym/api/v1.0/clases (8ms)
D/OkHttp: Content-Type: text/html; charset=utf-8
D/OkHttp: Content-Length: 192
D/OkHttp: Server: Werkzeug/0.11.11 Python/2.7.12
D/OkHttp: Date: Sat, 08 Oct 2016 23:19:00 GMT
D/OkHttp: OkHttp-Sent-Millis: 1475968739892
D/OkHttp: OkHttp-Received-Millis: 1475968739897
D/OkHttp: [[1, "halterofilia", "Profesor: XXXX YYYY. Clase de Halterofilia."], [2, "crossfit", "Profesor:ZZZZ TTTT. Clase de CrossFit"], [3, "halterofilia", "Profesor:XXXX YYYY. Clase de halterofilia"]]
D/OkHttp: <-- END HTTP (192-byte body)
D/ApiService: Error Occured: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0]
这是我运行Web服务的PyCharm提供的:
* Detected change in 'D:\\Proyectos\\PyCharm\\api-prueba\\api-prueba.py', reloading
* Restarting with stat
* Debugger is active!
* Debugger pin code: 195-275-846
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [09/Oct/2016 00:21:38] "GET /gym/api/v1.0/clases HTTP/1.1" 200 -
D/APIService:发生错误:java.lang.IllegalStateException:应为BEGIN_OBJECT,但在第1行第3列路径$[0]处为BEGIN_ARRAY
从这个错误中,您可以说它与期望的改型和API提供的内容不匹配。更具体地说,看起来像是reverfit期望的是单个对象,但您的API返回的是一个数组。我猜您正在尝试获取Clases对象的列表,而您的API发送了一个...数组。
为了使其工作,我将尝试获得如下所示的API响应:
[
{"id": 1, "name": "halterofilia", "title": "Profesor: XXXX YYYY. Clase de Halterofilia."},
{"id": 2, "name": "crossfit", "title": "Profesor:ZZZZ TTTT. Clase de CrossFit"},
{"id": 3, "name": "halterofilia", "title": "Profesor:XXXX YYYY. Clase de halterofilia"}
]
(id、名称和标题将替换为db字段的实际名称)
我试图隐藏Actionbar并改用工具栏,但如果我更改Theme.appcompat.light.NoActionBar,它确实会隐藏,但应用程序在行setContentView(r.layout.activity_main)处崩溃; 尽管它确实使用getSupportActionBar()隐藏。hide();但我不能用这个代码 Toolbar Toolbar=(Toolbar)findViewB
fReceiveBuffer是否存在一个视频帧? 哦,这里是我的FFMPEG初始化代码,需要打开相关视频解码器:http://paste.ubuntu.com/12529760//
问题内容: 为了使用webdriver.io测试我的React应用,我需要使用phantomjs启动它。 起初我以为问题出在webdriver.io,但我意识到当我尝试渲染时PhantomJS返回一个空白页。 为了进行一些测试,我编写了这个javascript文件: 我这样启动: 但是不管我做什么,总是空虚。 我目前使用React 0.14.7和phantomjs 2.1.1。有人对我为什么无法渲
我有一个主活动MainActivity,它是我的android应用程序的入口点。它通过发射器正确发射。然而,当我尝试执行startActivity时,我看到活动试图启动的一些调试,一些代码正确启动,但MainActivity从未启动。 我认为这可能与意图有关: 对吗? 从内部活动来看,我有 我甚至看到 10-11 22:23:46.026:INFO/ActivityManager(472):从pi
我是react native的新手,我正在尝试使用android Studio开始我的第一个项目。我遵循react native的“设置开发环境”中的说明,最终使用 然后我在android studio中打开了我的项目来启动AVD,但是gradle抛出了以下错误 错误:评估脚本时出现问题。 无法运行程序“node”(在目录“/home/deadshot/documents/playground/a
我是完全新的Web API的,并试图建立一个Android应用程序观看谷歌联系人。我被Oauth的第一步卡住了。我已经完成了登录按钮和授权。按钮工作正常,我可以登录我的谷歌账户,但当我试图从这个账户获得一些东西时,日志猫打印了这个按摩“I/System_Server:oneway函数结果将被删除,但以状态OK和包裹大小结束”。为什么会这样?因为auth令牌不再有效?如何恢复权限?我应该如何从帐户获